Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

About cast in integer constant expression (in standard C)

In standard C (I mean C99 or C11) we have the so-called integer constant expressions, which are constant expressions whose operands are all constant integers. There are other constraints, as to avoid comma operators in the expression.

However, other non-integer objects (even non-constant) are allowed in some special cases.
For example, if the sizeof operator is applied to an object whose size is known in translation time, this is allowed as part of an integer constant expression (note that sizeof always return an integer value).

Moreover, the explicit cast to an integer type is sometimes allowed too.
The standard C99 establish the following rule:

Standard C99, Section 6.6(par.6):

An integer constant expression) shall have integer type and shall only have operands that are integer costants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts.

Standard C99

My question is: Which is the exact meaning of "floating constants that are the immediate operands of casts"?

A floating constant is something like 3.14e+3, or well 0x2.11p-5.
That is, is not a general constant expression of type float, but only a floating point literal.
Then, I understand that only something like this is allowed in the definition above:

 (int) 3.14

but are not allowed operations involving floating literals.
This exclude cases as the following:

 (int) -3.14  /* The minus sign is not part of the constant: it is an operator */
 (int) (3.14) /* The parenthesis are an operator acting on the literal 3.14 */

The last case does not need to perform any floating point arithmetical operations in translation time, and it is equivalent to have the same without parenthesis: (int) 3.14.
However, it is not the immediate operand of a cast.

So, do we have to consider that (int) (3.14) is [part of] a valid integer constant expression or not (according to definition)?

On the other hand, the compiler GCC (with options: -std=c99 -pedantic-errors) gives me that (int) (3.14) is a valid integer constant expression, for example in a declaration as the following:

 #define BITW (int) (3.14)
 struct { unsigned bitfield: BITW } test;  // Translation success

(However, by doing #define BITW (int) (+3.14) it fails to translate, as expected).

like image 326
pablo1977 Avatar asked Feb 23 '14 18:02

pablo1977


People also ask

What is integer constant expression in C?

An integer constant is a value that is determined at compile time and cannot be changed at run time. An integer constant expression is an expression that is composed of constants and evaluated to a constant at compile time.

How do you write an integer constant?

Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.

What is unsigned integer constant in C?

Unsigned integer constant is an integer constant which has the permissible range from 0 to 65536. Thus significance of declaring a constant as unsigned almost doubles the size of the largest possible value.

What are the different integer constants in C++?

1) Decimal integer constant (base 10, the first digit is the most significant). 2) Octal integer constant (base 8, the first digit is the most significant). 3) Hexadecimal integer constant (base 16, the first digit is the most significant, the letters 'a' through 'f' represent the decimal values 10 through 15).


2 Answers

While poor choice of wording may imply that (int) (3.14) does not qualify as an integer constant expression, I think this is simply a bug in the wording. There is an analogous issue that's arguably a bug with the specification of NULL: it's allowed to be any null pointer constant, where null pointer constant is defined as either:

  1. an integer constant expression with value 0, or
  2. such an expression cast to void *.

However, to be useful as a definition for NULL, the expression should be properly parenthesized; all existing implementations I'm aware of do this. But by a strict reading, while (void *)0 is a null pointer constant, ((void *)0) is not (it's the application of the parentheses operator to a null pointer constant).

Ideally language should be added somewhere in the specification clarifying that parentheses do not affect things like this.

like image 174
R.. GitHub STOP HELPING ICE Avatar answered Nov 15 '22 04:11

R.. GitHub STOP HELPING ICE


For information, gcc maintainer and developer Joseph Myers has a discussion on its personal page about issues with constant expressions in the C99 Standard. The original text appeared on comp.std.c 10 years ago but has been expanded later.

http://www.polyomino.org.uk/computer/c/const-exprs-issues.txt

Among the issues with constant expressions he raised, the ones you described are discussed in his point (5):

(5) What are the "operands" (6.6 paragraphs 6 and 8) of a constant expression? Presumably it means the "ultimate" operands in some sense, recursing down various operators to their operands, but this isn't specified. Presumably compound literals such as (const int){0} are not meant to be constant expressions (being references to anonymous variables), but it is hardly clear from the text that 0 isn't the operand here. When compound literals appear in sizeof expressions whose results are not integer constants in unevaluated parts of expressions, whether the expressions are arithmetic constant expressions may depend on what casts are present in the compound literals. Also, one would expect that parentheses are meant to be purely syntactic rather than having "operands", so that (int)(0.0) is an integer constant expression just as (int)0.0 is, and ((void *)0) is a null pointer constant, but this is nowhere stated.

In his personal page referring to this text, it is written:

I also have a discussion of issues with constant expressions (not in the form of the pre-DRs above; parts may become DRs following implementation experience).

To my knowledge the terminology question raised by point (5) has not been further raised in a DR.

like image 24
ouah Avatar answered Nov 15 '22 05:11

ouah