leeman
leeman

Reputation: 490

C float assignment from literal

While reading part of a book about 3D graphics I came across the following assignment:

const float vertexPositions[] = {
0.75f, 0.75f, 0.0f, 1.0f,
0.75f, -0.75f, 0.0f, 1.0f,
-0.75f, -0.75f, 0.0f, 1.0f,
};

Why is the f suffix necessary? Can the type of the literals not be determined from the type of the variable? I believe that without the f float literals are interpreted as doubles, but why when the array is clearly of type float?

Upvotes: 4

Views: 1618

Answers (4)

AnT stands with Russia
AnT stands with Russia

Reputation: 320621

  1. Some terminological nitpicks.

    • This is not an assignment, it is an initialization.
    • What you have between the {} (e.g. 1.0f) are not literals, they are constants. C only has string literals and compound literals and that's it. In C 1.0 is a floating-point constant.
  2. In C language the type of the right-hand side (of an assignment or an initialization) is never influenced by the type of the left-hand side. The type of the value on the right-hand side is always determined independently. It is determined solely from how that value is specified. Left-hand side is never taken into consideration. Then, once the type of the right-hand size is known, the original value is converted to the type of the left-hand side. In other words, constant 1.0 is always a constant of type double, even if you use it to initialize a float object.

  3. There's nothing incorrect with using a double constant (like 1.0) to initialize an object of type float. As I said above, the double value will be converted to float type. However, some compilers issue a warning about that conversion, notifying the user about a possible precision loss. Specifically to subdue that warning people'd use an explicit float suffix (e.g. 1.0f) or an explicit cast to float (e.g. (float) 1.0) when initializing float objects. This does not look good, since it goes against the DRY (Don't-Repeat-Yourself) rule, but in real life this method of dealing with warnings is encountered quite often.

Upvotes: 1

Pascal Cuoq
Pascal Cuoq

Reputation: 80305

The float array initialization in your example is fine in C, as it would be if it used double constants. For the values at hand, it would also be fine if it were a double array initialized with float constants, because the values at hand are exactly representable as float. There would be no reason for a compiler to emit a warning even in this last case, although it would be strange and confusing that the developer bothered to type additional suffixes that do not match the eventual type.

In short, the author is only being explicit, which, in the case of a float array, is good.

For arbitrary values written in decimal, you do not want to initialize float variables with double constants because of “double-rounding” (in which the word “double” means twice and does not refer to the type of the same name). If you initialize f1 and f2 as follows, they end up with different values, and f1 is actually the closest to the intended value 1.01161128282547:

  float f1 = 1.01161128282547f;
  float f2 = 1.01161128282547;

The explanation is that in the case of f2, the decimal value 1.01161128282547 is first rounded to the nearest double, and then to the nearest float. These two steps introduce more error than directly rounding to the nearest float, which is how f1 is initialized.

Upvotes: 5

pqnet
pqnet

Reputation: 6598

No, type of literal is never inferred. Without the f they are double literals, and the instruction is a conversion which may lose precision (not really in this case because all the literals are exactly represented with float too).

Same warning you get if you do

float x = 3.0;

Upvotes: 0

Igor Pejic
Igor Pejic

Reputation: 3698

Although you may not get no errors for omitting the f it is good practice to put it and there are several reasons why, for example:

float num = 0.1;
(num == 0.1)

The evaluation will produce 0 because num is rounded to 0.1 as a float and 0.1 in the expression is double. So they are actually not the same, although they may seem to be.

Upvotes: 0

Related Questions