Wojciech Morawiec
Wojciech Morawiec

Reputation: 256

Correct definition of constants

I'm having a little trouble defining the constants I use in my code in a correct way. Although I read the excellent post Jonathan Leffler over at How do I use extern to share variables between source files?, I seem to have misunderstood something. This is the setup:

/*   constants.h   */
extern int NUM_PARTICLES;
extern int LIGHTSPEED;

This header is used in random.h and main.c, which looks like

#include "constants.h"
int NUM_PARTICLES=104;

in random.h or

#include "constants.h"
int LIGHTSPEED=104;

in main.c, respectively. NUM_PARTICLES is used in main.c in

30:  double ghosts[NUM_PARTICLES][4];
31:  double output[NUM_PARTICLES][3];

Although this thing works, I get the following warnings,

main.c: In function ‘int main()’:
main.c:30:32: warning: ISO C++ forbids variable length array ‘ghosts’ [-Wvla]
main.c:31:32: warning: ISO C++ forbids variable length array ‘output’ [-Wvla]

which is weird, because in my opinion I do give the array a constant value that is known at compilation time. (And usually these array length errors cause some segfaults, which in this case they do not.) Any ideas?

Upvotes: 1

Views: 89

Answers (1)

Jon
Jon

Reputation: 437376

Short story: this is a quirk of C.

Normally, you would define an integer constant as

const int LIGHTSPEED = 104;

The problem is that according to the language rules this constant is not a constant expression, and thus cannot be used to specify the size of a statically allocated array.

The relevant part of the C standard (6.6/6, I am not making this up) defines what an integer constant expression is:

An integer constant expression 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.

There are two solutions for this. The classic one is to use a macro, which simply pastes 104 between the angle brackets before the compiler sees the code, therefore making the array size an integer constant:

#define NUM_PARTICLES 104

The better one (IMO) is to avoid a macro because you can, and use an enum, which is possible (you are using an enumeration constant):

enum { NUM_PARTICLES = 104 };

Upvotes: 5

Related Questions