10

I am using the following code.

const int X_ORIGIN = 1233086;             
const int Y_ORIGIN = -4728071;              
const int Z_ORIGIN = 4085704;
const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

When I compile it, GCC gives me the following error.

Transformations.h:16:1: error: initializer element is not constant

What does that mean? How can I fix my code?

apaderno
  • 28,547
  • 16
  • 75
  • 90
CodeKingPlusPlus
  • 15,383
  • 51
  • 135
  • 216
  • 2
    Why not create a struct which contains the three positions, rather than an array? Seems a bit counter-intuitive... – Nathan White Jul 18 '12 at 12:17
  • corollary to what @nathanwhite said, John Carmack said: https://twitter.com/ID_AA_Carmack/status/219884864185446402 – Michael Buen Jul 18 '12 at 12:52
  • Related: *[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 09:21
  • `NUM_DIMENSIONS` isn't defined anywhere, and there's no line 16 in this program. It's just not reproducible. – Toby Speight Jul 29 '23 at 12:03

6 Answers6

21

Often people are mislead by the naming of the keyword const, implying something of a constant value that can't be changed. In C at least, it means readonly. const qualified objects at file scope are not having the proper constness to serve as array initializers.

As an example for non-constant constness, it is perfectly ok to declare

 const volatile unsigned int milliseconds_since_boot;

being a value that gets updated from outside the compiler's control (think HW register) and that you are not allowed to assign to, i.e. it is readonly.

Jens
  • 69,818
  • 15
  • 125
  • 179
  • 2
    Not my DV, but you could elaborate a bit cloaser on OPs actual problem. The example is hard to comprehend for beginners who might not even know what a "HW register" is. – too honest for this site Sep 12 '16 at 11:26
14

You can't do this at global scope in C, only at local scope, i.e. within a function:

#define NUM_DIMENSIONS 3

const int X_ORIGIN = 1233086;             
const int Y_ORIGIN = -4728071;              
const int Z_ORIGIN = 4085704;

const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN}; // FAIL

void foo(void)
{
    const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN}; // OK
}

Alternatively you could compile the code as C++ rather than C.

Paul R
  • 208,748
  • 37
  • 389
  • 560
5

I'm not a proper programmer ;) but I'd do this:

#define X_ORIGIN (1233086)
#define Y_ORIGIN (-4728071)
#define Z_ORIGIN (4085704)
const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

That way it's just a text-substitution. If the compiler still spits the dummy at least you're a step closer to knowing where the issue is.

John U
  • 2,886
  • 3
  • 27
  • 39
  • 4
    @nathanwhite Care to elaborate? The macros solve the problem just fine! (Assuming `NUM_DIMENSIONS` is defined somewhere). – Jens Jul 18 '12 at 13:18
  • 2
    @nathanwhite Those are precisely the causes for the "initializer element is not constant" error(s). Having `NUM_DIMENSIONS` as a variable (const qualified or not), causes a "variably modified »xyzOrigin« at file scope". – Daniel Fischer Jul 18 '12 at 16:48
  • 1
    Better still would be to remove `NUM_DIMENSIONS` altogether and let the array size itself to the number of elements provided. – Alex Celeste Jun 07 '13 at 19:01
4

As an alternative, this would also work in this case:

enum { X_ORIGIN = 1233086,
       Y_ORIGIN = -4728071,
       Z_ORIGIN = 4085704 };

const int xyzOrigin[] = { X_ORIGIN, Y_ORIGIN, Z_ORIGIN };

int main()
{
    return 0;
}
hmjd
  • 120,187
  • 20
  • 207
  • 252
2

In C language objects with static storage duration has to be initialized with constant expressions or with aggregate initializers containing constant expressions. --Answer of AndreyT

After reading, You must have the knowledge that NUM_DIMENSIONS, If it has the const-qualification, isn't a constant! Then you can't initializate your array this way.

For use this code:

const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

You should use: #define NUM_DIMENSIONS 3 or you could just declare without any variable inside the square brackets const int xyzOrigin[] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

Community
  • 1
  • 1
waldyr.ar
  • 14,424
  • 6
  • 33
  • 64
0

As triclosan said:

main()
{
    const int X_ORIGIN = 1233086;
    const int Y_ORIGIN = -4728071;
    const int Z_ORIGIN = 4085704;
    const int xyzOrigin[] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};
}

this works fine...

or, if you know the dimensions beforehand, this:

#define DIM 3

main()
{
    const int X_ORIGIN = 1233086;
    const int Y_ORIGIN = -4728071;
    const int Z_ORIGIN = 4085704;
    const int xyzOrigin[DIM] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};
}
Bruno Oliveira
  • 735
  • 10
  • 20