I take my main.c file and compile it with gcc -std=c1x -c main.c in Mac OS X, and it works fine with no errors. Then I do the exact same thing in LinuxMint and on a Raspberry Pi, and in both cases, it gives me errors about "initializer element is not constant".
One example of a problematic line with relevant code:
//STATIC GLOBAL CONSTANTS
const unsigned long long LATITUDE = (long) 3600000;
const unsigned long long LONGITUDE = (long) 1810000;
const unsigned long long MAX_COORDINATES_NUMBER = (LATITUDE-1) + LATITUDE*(LONGITUDE-1); //compiler error: initializer element is not constant
It's supposed to let me do arithmetic, right? I could just replace that with the actual numbers, and it would work, but then it would become messy. And it works fine on my Mac anyway. Is there some option in GCC I have to specify on Linux (besides -std=c1x, which you also don't need on Mac)?
The C language requires the initializer for a static object to be a constant expression. (Since initialization of static objects occurs before
main
begins, there's no place for any run-time evaluation to happen.)C's
const
keyword does not mean "constant", though the words are obviously related. A constant expression is one that can be, and in some cases must be, evaluated at compile time.const
means read-only. For example, at block scope (inside a function definition), this:is perfectly legal. Obviously the initializer can't be evaluated at compile time; the
const
merely means thatr
may not be modified after it's been initalized.When you write:
a reference to
LATITUDE
is not a constant expression. A compiler certainly could evaluate such a reference at compile time, but the C standard doesn't require it to. (The line between constant and non-constant expressions had to be drawn somewhere, and the authors of the language chose to make the distinction relatively simple, with few special cases.)Now it's certainly true that the C language could have been defined so that
LATITUDE
is a constant expression. It is in C++, and I've argued for C to adopt a similar rule. But under current C rules, it's not, which means that you can't useLATITUDE
in the initializer for a static object.This also means that
clang
(the compiler that, as I understand it, is the one invoked when you typegcc
under MacOS) is very likely non-conforming, because it fails to diagnose this error. On my own Linux system, I find that, when invoked with-std=c11 -pedantic
, gcc 4.7.2 correctly diagnoses the error, but clang 3.4 does not.Except perhaps for this clause from section 6.6 paragraph 10 of the 2011 ISO C standard (which also exists in the 1990 and 1999 standards):
It's conceivable that clang accepts
LATITUDE
as a constant expression because it takes advantage of this permission -- but then I'd still expect at least a warning fromclang -std=c11 -pedantic -Wall -Wextra
, and there is none.UPDATE : When I compile the following:
with clang 3.0 with options
-std=c99 -pedantic
, I get:With clang 3.4, the warning is:
So clang does recognize that it's not a constant expression; the bug is that it doesn't warn about the declaration of
MAX_COORDINATES_NUMBER
.ANOTHER UPDATE :
The code in the question is:
The
(long)
casts in the first two declarations are not useful. The constants3600000
and1810000
are (probably) of typeint
. You convert them tolong
and then use the result to initialize an object of typeunsigned long long
. Just drop the cast -- or, if you want to be more explicit, add aULL
suffix to make the constantsunsigned long long
:The problem is on the third declaration, which refers to
LATITUDE
andLONGITUDE
, neither of which is a constant expression. Unfortunately C doesn't provide a good way to define named constants of integer types other thanint
(you can (ab)use theenum
feature forint
constants). The alternative is to use macros. This works:And if you need
MAX_COORDINATES_NUMBER
to be a constant expression, you can make it a macro as well:(The extra parentheses are needed to avoid operator precedence problems when you use
MAX_COORDINATES_NUMBER
in a larger expression.)