2

Consider the following question from a previous paper on C:

Show step-by-step how the following C expression is evaluated, giving the value of the expression and the type of that value.

9 / 3 / 2 * 6 + 2 * 1.5

Is the type a float or a double? Could someone please clarify? (Note the lack of an explicit type in the question.)

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Faz Hassan
  • 33
  • 5
  • 5
    The floating point constants have a type of `double`. If suffixed with `f` (like `1.5f`), then `float`. – Eugene Sh. May 17 '17 at 18:01
  • 1
    And all the other constants have type `int`. – Sneftel May 17 '17 at 18:01
  • 2
    @Sneftel, not quite: there can be constants suffixed with, say, `UL` (unsigned long) or `U` (unsigned int). – hidefromkgb May 17 '17 at 18:05
  • All the reference material you would need to fully answer that question: http://en.cppreference.com/w/c/language/operator_precedence http://en.cppreference.com/w/c/language/integer_constant http://en.cppreference.com/w/c/language/floating_constant – PeterSW May 17 '17 at 18:07
  • 4
    @hidefromkgb I was referring to the constants in the OP's posted code. Clearly it's possible to have constants in C with a type other than `int`. – Sneftel May 17 '17 at 18:08

4 Answers4

12

According to the usual arithmetic conversions (6.3.1.8 Usual arithmetic conversions)

Otherwise, if the corresponding real type of either operand is double, the other operand is converted, without change of type domain, to a type whose corresponding real type is double.

the answer:

  1. 9 / 3 = 3 (int)
  2. 3 / 2 = 1 (int)
  3. 1 * 6 = 6 (int)
  4. 2 * 1.5 = 3.0 (double)
  5. 6 + 3.0 = 9.0 (double)
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Mikhail Romanko
  • 396
  • 1
  • 9
5

In your expression 1.5 is a double (in order for the compiler to treat it a a float it should have an f suffix: 1.5f). All of the other numbers are of type int.

In order to show how the 9 / 3 / 2 * 6 + 2 * 1.5 expression will be evaluated, look at the C Operator Precedence for reference (both priority and associativity). Note that 2 * 1.5 will be of type double (and so the type of the whole expression).

syntagma
  • 23,346
  • 16
  • 78
  • 134
2

It is a double.

As mentioned in Kernighan & Ritchie's "The C programming language":

Floating-point constants contain a decimal point (123.4) or an exponent (1e-2) or both; their type is double, unless suffixed.

A quick way to find out for yourself would also be to write that code: printf("%d %d\n", sizeof(1.5)==sizeof(double), sizeof(1.5)==sizeof(float)); which will output 1 0 indicating that 1.5 is a double.

Edit: Of course, type sizes in C are system dependent, so that code should not be entirely trusted.

kyriakosSt
  • 1,754
  • 2
  • 15
  • 33
  • 3
    K&R are outdated. The [C standard](http://port70.net/~nsz/c/c11/n1570.html#6.4.4.2p4) would be a better reference. – Eugene Sh. May 17 '17 at 18:12
  • 2
    Note that the result of `printf("%d %d\n", sizeof(1.5)==sizeof(double), sizeof(1.5)==sizeof(float));` could be 1 1 - although that is not so common. `_Generic` is a better discriminator. – chux - Reinstate Monica May 17 '17 at 18:12
  • @EugeneSh. : Since it was a question from an exam, I supposed the original book should be a good reference. – kyriakosSt May 17 '17 at 18:41
  • 1
    @chux : Indeed, it is hardware/system dependent, however it is straight forward for proving a point. One shouldn't depend on that while writing code. – kyriakosSt May 17 '17 at 18:41
  • @Eugene Sh: The K&R text is the first authoritative work on C by those who invented the language and still merits a modicum of respect. It allows one to acquire basic C99 concepts or refresh their knowledge of it. What K&R has to say about floats vs doubles still rings true. – slevy1 May 17 '17 at 20:41
  • @slevy1 With all of the respect to K&R, some of the things described there are just incorrect about modern C. And one can't know which ones exactly without consulting the modern standard. In this specific case it appears to be correct. But how can you be sure about that? – Eugene Sh. May 17 '17 at 20:46
  • @Eugene Sh: https://en.wikipedia.org/wiki/The_C_Programming_Language#/media/File:The_C_Programming_Language_cover.svg (2nd edition reprinted in 2016) – slevy1 May 18 '17 at 00:04
1

This problem may also be resolved by utilizing an approach based on reflection. One may compare the type of the expression with a float and then with a double by using __builtin_types_compatible_p(). This function determines whether two types are the same. For this purpose, __typeof__ can handily retrieve the type of the expression and pass it to the built-in function, as follows:

#include <stdio.h>

int main() {
    if (__builtin_types_compatible_p(__typeof__(9 / 3 / 2 * 6 + 2 * 1.5), float)) {
        puts("float");
    } else if (__builtin_types_compatible_p(__typeof__(9 / 3 / 2 * 6 + 2 * 1.5), double)) {
        puts("double");
    }
    return (0);
}

See demo.

When the types are the same, the function returns 1; see more here.

Note: __typeof__ does not return a string but a system type.

Instead of providing the entire mathematical expression to typeof, one may simply pass 1.5 since the question really turns on what data type represents this floating-point value.

See related information: Syntax and Sample Usage of _Generic in C11.

Community
  • 1
  • 1
slevy1
  • 3,797
  • 2
  • 27
  • 33