0

I'm working through some openGL tutorials and since they all have C++ syntax I need to convert them to C syntax and I have some problems with global variables.

So I have my extern declarations in the shared header LUtil.h

#ifndef LUTIL_H
#define LUTIL_H

#include "LOpenGL.h"
#include <stdio.h>
#include <stdbool.h>

//Color modes
extern const int COLOR_MODE_CYAN;
extern const int COLOR_MODE_MULTI;

//Screen constants
extern const int SCREEN_WIDTH;
extern const int SCREEN_HEIGHT;
extern const int SCREEN_FPS;

extern int gColorMode;
extern GLfloat gProjectionScale;
...

And I have my LUtil.c file in which the declaration happens

#include "LUtil.h"

//The current color rendering mode
const int COLOR_MODE_CYAN = 0;
const int COLOR_MODE_MULTI = 1;

//constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_FPS = 60;

//The projection scale
int gColorMode = 0;
GLfloat gProjectionScale = 1.f;
...

Now if I compile like this it works. But if I initialize the gColorMode constant like this in LUtil.c

int gColorMode = COLOR_MODE_CYAN;

I get a compiler error saying that my initializer is not constant despite having declared COLOR_MODE_CYAN a const and initializing with it.

Why is this?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Keya Kersting
  • 135
  • 1
  • 1
  • 8

3 Answers3

4

In C, a variable declared const is not a constant, it's called const-qualified variable. It is not considered a compile time constant expression.

You need to either use an integer constant or a #define to get your work done.

FWIW, a variable with const is a real constant (integral constant expression) in case of C++.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Do not use magic number is code (well, there are exceptions). FYI: "literal constant" (I'd also prefer this) is a non-standard term. The standard uses [_(integer) constant_](http://port70.net/~nsz/c/c11/n1570.html#6.4.4). This alone shows that C does not have true constants (and C++ has a kind of chimera only actually). – too honest for this site Aug 03 '15 at 12:27
  • @Olaf Thank you sir, just as mentioned in 6.4.4, updating my answer now. :-) – Sourav Ghosh Aug 03 '15 at 12:29
  • No need to update actually, It was fine for me already. (I'm just trying to add some background - can't help doing it:-) – too honest for this site Aug 03 '15 at 12:30
  • Fine, thanks. Weather getting hot here:-( Hope your fine, too. I did not see it as a mistake, because _literal_ is a common term and the C commitee should have use that consistently, see [_string literal_](http://port70.net/~nsz/c/c11/n1570.html#6.4.5). A bit strange they did added `enum` constants here (which is not a syntax element, but an identifier). Well. so much for consistency... – too honest for this site Aug 03 '15 at 12:36
  • @Olaf Today I appeared late here, was overdosed with some urgent work, just now finished. It's monsoon here, so it's actually cool. regarding the "lireral",as of now, there's only `string literal` mentioned in the standard, as you very rightly mentioned. all others are -constant :-) – Sourav Ghosh Aug 03 '15 at 12:41
  • More important, they mixed the `enum` constant _identifier_ in. That does actually not belong there, as this differentiation si not done by pure syntax anylysis, but the semantics (property of the _identifier_). I smell the malodour of legacy stuff) – too honest for this site Aug 03 '15 at 12:48
  • Thank you for clarifying. I was actually looking for `define` and it was catered to my needs. Though I'm still new to macros and my coding is a bit shaky, but it works. – Keya Kersting Aug 03 '15 at 13:33
1

const in C doesn't actually create a "constant". You still end up with a variable (reserved memory) but the compiler just forbids writes to that variable.

Even though it is marked const, you could cast it back to non-const and modify it (please don't!) Because of this (and possibly other reasons), it requires emitting a memory read to access the value of your const int constants, which is not allowed when initializing another variable (it must be a compile-time constant.)

Instead, use a #define in your header file.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • 1
    I agree that those 'const' values in the header file should have been #defines. Then the compiler problem would never have surfaced, and the value would not be changable and no memory space would be taken I would have placed the #defines directly in the header then the only extern statements would be gProjectionScale and gColorMode – user3629249 Aug 03 '15 at 12:59
0

const int COLOR_MODE_CYAN

is still a variable even if it is constant(which just means that compiler will throw a compile time error if you try to modify it using code). Which means it will have a memory location and a value, when the program will be loaded into memory. Its value can be calculated by the = operator. And all the operators should be placed inside a function definition because they can be resolved only at run time.

And since the variable which you are assigning the value to is a global variable. Its initial value must be declared at compile time so that the compiler can put it into an appropriate segment(.bss or .data). But the assigned value is a variable, and in order to find out its value = operator has to be executed. Which can not be done at compile time. So that compiler is throwing an error that GIVE ME A CONSTANT VALUE THAT I CAN ASSIGN TO THIS GLOBAL VARIABLE LIKE 3, 4, 5.

Amit Bhaira
  • 1,687
  • 6
  • 18
  • 31