7

What's wrong with the following code?

#define DELAY_CYCLES ((int)(0.1/0.001))
typedef struct {
    double state_history[N_X][DELAY_CYCLES];
    double foo;
} foo

GCC complains:

main.h:52:3: warning: variably modified 'state_history' at file scope

Is it because the int cast can't be done at compile time for some reason?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
allanw
  • 73
  • 1
  • 3
  • Possible duplicate: *[Variably modified array at file scope in C](https://stackoverflow.com/questions/13645936/variably-modified-array-at-file-scope-in-c)*. – Peter Mortensen Jul 29 '23 at 11:02
  • Does this answer your question? [Variably modified array at file scope in C](https://stackoverflow.com/questions/13645936/variably-modified-array-at-file-scope-in-c) – Toby Speight Jul 29 '23 at 11:40

2 Answers2

16

EDIT AGAIN

If you follow the standard to the letter, then yes, you should avoid floating-point expressions there. In C, with the sole exception of floating-point constants cast to integers (such as (int)3.0f), floating-point expressions are not considered integer constant expressions at compile time for the purpose of array size calculations. You need to modify the definition to avoid floating-point numbers and use integers exclusively.

In order not to be a variable length array, array sizes are required to be "integer constant expressions" (C99 §6.7.5.2/4), and an "integer constant expression" is defined in §6.6/6 (emphasis mine):

An integer constant expression96) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof operator.

It appears that GCC only added that warning in version 4.5. In 4.4 and below, it does not report any warnings for that code, even with -Wall -Wextra -ansi -pedantic. However, to be safe and 100% portable, you should change the definition of DELAY_CYCLES to avoid floating-point expressions.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • I'm using gcc 4.5.2. I get the warning even with taking the N_X out. Didn't have to use any extra warning flags. – allanw Jan 25 '11 at 03:44
  • But what if I don't *want* to be portable. I'm compiling a program which will only ever be run on the machine that I compile it on, and it's a warning, so gcc *can* and does compile my program successfully. The floating point number in my code is a dimension of a real-world object which determines the array size, so I can't use an integer. I should be able to suppress the warning using #pragma 'warning' disable, but gcc doesn't tell me which warning to disable. – Richard Parkins May 11 '23 at 04:40
6

Even if it were an integer constant expression, (int)(0.1/0.001) could easily be either 99 or 100, since the values 0.1 and 0.001 do not exist in floating point. Determining which value IEEE 754 specifies would require checking both of 0.1 and 0.001 to see whether they're closer to their neighbors above or below, then actually doing the division of those neighbors - or just checking it on a conformant system. However this is one place where I would not want to rely on the implementation being conformant to get the right answer.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711