buffer[0] = ((float)(( buffer[0] + buffer[1])/3)+0.8);
int buffer[100];
I haven’t been able to find a satisfactory answer yet, and I can’t run this code at the moment to test.
I’ve inherited an embedded C code base with equations like above where an individual just casts the whole equation to a float.
I understand integer math and if you are doing something like division with integers then at least one needs to be casted to a float to get an accurate answer instead of a truncated answer. But I’ve never seen casting an entire equation to a float.
My questions are:
Will this result in the compiler treating everything as a float?
Does the equation in parentheses get done first and then the result casted to a float? In that latter case,
(buffer[0] + buffer[1])/3)
would be integer division and the decimal truncated before being promoted to a double for the addition to 0.8.
Any ideas?
- Will this result in the compiler treating everything as a float?
No. A cast says to convert the value of the operand to the cast type. It does not affect evaluation inside the operand.
- Does the equation in parentheses get done first and then the result casted to a float?
There is an expression inside the parentheses, not an equation. (See below.)
C evaluates the parts of an expression independently, without consideration for the expression they are contained in, and it evaluates the subexpressions independently, and so on. (There are limited exceptions, such as sizeof expression
merely analyzes expression
to determine its type; it is not evaluated.)
In buffer[0] = ((float)(( buffer[0] + buffer[1])/3)+0.8)
:
buffer[0] + buffer[1]
, buffer[0]
and buffer[1]
are added. (Depending on their values, this could overflow, and the behavior would not be defined by the C standard.)( buffer[0] + buffer[1])/3
, the sum is divided by 3 using int
arithmetic, which truncates fractions, thus rounding results toward 0.(float)(( buffer[0] + buffer[1])/3)
, the result of the division is converted to float
. This can also overflow and have undefined behavior.(float)(( buffer[0] + buffer[1])/3)+0.8
, 0.8
is added to the float
resulting from the previous step.int
(which truncates toward zero) and assigned to buffer[0]
. (The conversion to int
is because the target of the assignment, buffer[0]
, has that type.)An equation is an assertion that two expressions have the same value. y = x2 is an equation. x2 is not an equation. It is an expression.
This code is almost certainly wrong, because the result of the int
division is an integer, and therefore adding 0.8
immediately before the assignment will not change a nonnegative result. For example, if the division produces 5, the conversion to float
will also produce 5 (as a float
), and then the implicit conversion to double
will produce 5, and the addition of 0.8
will produce (approximately) 5.8. Then the conversion to int
for assignment to buffer[0]
will produce 5. So it will be as if the 0.8
were not added.
If the division produces a negative value, the addition will change it. For example, if the division produces −5, the conversion to float
and then double
will also produce −5, and then the addition of 0.8
will produce (approximately) −4.2. Then the conversion to int
will produce −4. So, it is hypothetically possible the author added 0.8
because they wanted to add one to a negative quotient but keep nonnegative quotients unchanged. But I would have done that by adding a simpler constant, say 0.5, and clearly documenting its purpose.
Even if the code were intended to do this, the conversion to float
appears is unnecessary. For the expression with + 0.8
, the left operand would be automatically converted to double
. For integer values that do not overflow float
, converting to float
and then double
produces the same result as converting to double
. This is a further sign this code is poorly written.