3

I'd like to initialize an array based on a calculation, but the compiler gives me an error when I try this (I'm using GCC version 6.3.0):

const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
char textgrid[SCREEN_HEIGHT/16][SCREEN_WIDTH/16];

The compiler error is as follows:

error: variably modified 'textgrid' at file scope

Is there a way to do this at file scope?

It seems I can't use calculations as part of a #define statement to accomplish this, because the following gives me the same error:

#define TEXTGRID_WIDTH (SCREEN_WIDTH / 16)
#define TEXTGRID_HEIGHT (SCREEN_HEIGHT / 16)
char textgrid[TEXTGRID_HEIGHT][TEXTGRID_WIDTH];
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
dvanaria
  • 6,593
  • 22
  • 62
  • 82

3 Answers3

5

According to the C Standard (6.7.6.2 Array declarators)

  1. ... If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type.

and (6.7.6.2 Array declarators)

2 If an identifier is declared as having a variably modified type, it shall be an ordinary identifier (as defined in 6.2.3), have no linkage, and have either block scope or function prototype scope. If an identifier is declared to be an object with static or thread storage duration, it shall not have a variable length array type.

and at last (6.6 Constant expressions)

6 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. 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.

So you can use either defined named constants like

#define SCREEN_WIDTH  800
#define SCREEN_HEIGHT 600

or enumerators

enum { SCREEN_WIDTH = 800, SCREEN_HEIGHT = 600 };
tom
  • 21,844
  • 6
  • 43
  • 36
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 2
    I do not think throwing quotes from the standard at people without explaining is a good for teaching. In order to understand a quote from the standard, people must have a good deal of fundamental knowledge already. But people asking basic questions are generally not at that level yet. For example, people who have learned high school and college math have seen “Let x = 3” for years in math texts, so they are used to thinking that a name can actually **be** a value. To teach them programming, we have to teach them a new concept, that a name identifies an object, and the value is in the object. – Eric Postpischil Jan 06 '18 at 19:41
  • 1
    @eric I disagree, as the answer is not for the OP alone. It is for anyone coming through the internet, and answers are ought to be of high quality. – machine_1 Jan 06 '18 at 19:46
  • 2
    @machine_1: Anybody looking for an answer to this question is likely to be at the same level. And how would explaining things impair quality? I did not say to remove the quotes, just that throwing them at people without explaining is not good for teaching. Explain the concepts in a way **suitable for the knowledge of the reader**. Then, if you wish, back up the answer with quotes from the standard. – Eric Postpischil Jan 06 '18 at 19:51
4

In C, a const qualified variable is not considered a compile time constant. You'd be needing a compile time constant to mention the array dimension in file scope.

You can make use of #define statements for this purpose.

machine_1
  • 4,266
  • 2
  • 21
  • 42
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
4

When you write const int SCREEN_WIDTH = 800, you define an object named SCREEN_WIDTH that contains the value 800.

Because SCREEN_WIDTH is an object, not a value, you cannot use it for a value in a constant expression. Even though its value is unchanging and obvious to us, it does not qualify as a compile-time constant.

To define an array at file scope, you must use dimensions that are constant expressions (expressions formed entirely of compile-time constants).

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312