0

I know there is some questions related to this error:
question 1, question 2, question 3, question 4,...

The difference is, I don't use variables to define the size, but macros.

Here is what I do:

#define     SIZE_A      250                      // Real world value
#define     SIZE_B       80                      // Real world value
#define     SCALE         0.25                   // Real world value
#define     TOTAL_A     (uint16_t)(SIZE_A/SCALE)
#define     TOTAL_B     (uint16_t)(SIZE_B/SCALE)
#define     TOTAL       TOTAL_A*TOTAL_B

#define     SIZE_1      (uint16_t)(TOTAL*0.3)


#define     SIZE_2      4000

typedef struct {
    toto_t  toto[TOTAL_A][TOTAL_B];
    foo_t   foo[SIZE_1][SIZE_2];
} bar_t;

As you can see, I've got three macros (SIZE_A, SIZE_B, SCALE) which represent real things. From those I define the sizes (TOTAL_A, TOTAL_B) of a 2 dimensional array (toto_t toto), and the total number of cells in this array (TOTAL). Then I take a piece of that total (SIZE_1) to define the size of an other array I want to create (foo_t foo).

This way, GCC throws the error: Variably modified 'foo' at file scope. So, I looked at the preprocessor output:

typedef struct {
    toto_t toto[(uint16_t)(250/0.25)][(uint16_t)(80/0.25)];
    foo_t  foo[(uint16_t)((uint16_t)(250/0.25)*(uint16_t)(80/0.25)*0.3)][4000];
} bar_t;

As we can see, the preprocessor is doing is job well. All macros are replaced by the literal value. So there is only constant values in the array size.

My question

Why can GCC not compute the sizes of the arrays? And is there an option to force it to do the computation?

I compile with this option -O3 -Wall -Wextra -Werror.

Testing:

Create a test.h and put the code I posted and add typedef uint16_t toto_t; typedef uint16_t foo_t; at the beginning. And create a test.c file with:

#include <stdio.h>
#include <inttypes.h>

#include "test.h"

int main() {
    printf("hello world\n");

    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Phantom
  • 833
  • 1
  • 9
  • 26
  • 2
    Why do you replace the minimal example I've made for you and that perfectly reproduces your problem by a description of code?? – Jabberwocky Dec 13 '19 at 09:21

1 Answers1

0

The problem here is the floating value of SCALE.

You can avoid it using fixed point value:

#define     SIZE_A      250                      // Real world value
#define     SIZE_B       80                      // Real world value
#define     SCALE         25                   // Real world value
#define     TOTAL_A     (SIZE_A*100/SCALE)
#define     TOTAL_B     (SIZE_B*100/SCALE)
#define     TOTAL       TOTAL_A*TOTAL_B

#define     SIZE_1      (TOTAL*3/10)

#define     SIZE_2      4000

typedef struct {
    toto_t  toto[TOTAL_A][TOTAL_B];
    foo_t   foo[SIZE_1][SIZE_2];
} bar_t;

This answer will give you all information about C standard rules.

PunyCode
  • 373
  • 4
  • 18
LPs
  • 16,045
  • 8
  • 30
  • 61
  • 1
    I can't change the `SCALE` value, because I use it to do some other computation. It will complexify the reste of the code – Phantom Dec 13 '19 at 08:27
  • 1
    @Phantom: The C standard requires an *integer constant expression* for the array size in this context. It may not contain floating-point operations. If you cannot change `SCALE`, you will have to use some other way of managing the data that does not declare arrays at file scope or in structures that use `SCALE` in their sizes. – Eric Postpischil Dec 13 '19 at 08:37
  • 1
    @Phantom Simple: you cannot do what you want to do. Take a look at [This question](https://stackoverflow.com/questions/38054023/c-fixed-size-array-treated-as-variable-size) – LPs Dec 13 '19 at 08:40
  • 1
    @LPs Yes it answer my question. But I can do want I want. :p From what you propose I just add an other macro `#define SCALE_2 (SCALE/100)`. And then use this macro. Thanks for you answer – Phantom Dec 13 '19 at 08:50
  • 1
    @LPs interestingly it compiles [with clang, but not with gcc](https://www.godbolt.org/z/hQCuFs). – Jabberwocky Dec 13 '19 at 09:12
  • 1
    @Jabberwocky [Not if you compile with the correct standard adding](https://www.godbolt.org/z/GHu6TS) `-std=c99` or `-std=c11`.... – LPs Dec 13 '19 at 09:37