Ответ 1
Для языка C требуется инициализатор для статического объекта как константное выражение. (Поскольку инициализация статических объектов происходит до начала main
, нет места для любой оценки времени выполнения).
C const
ключевое слово не означает "константа", хотя слова, очевидно, связаны между собой. Постоянное выражение - это выражение, которое может быть и в некоторых случаях должно быть оценено во время компиляции. const
означает только чтение. Например, в области блока (внутри определения функции) это:
const int r = rand();
является совершенно законным. Очевидно, инициализатор не может быть оценен во время компиляции; const
просто означает, что r
не может быть изменен после его инициализации.
Когда вы пишете:
const unsigned long long LATITUDE = (long) 3600000;
ссылка на LATITUDE
не является константным выражением. Компилятор, конечно, мог бы оценить такую ссылку во время компиляции, но стандарт C не требует этого. (Строка между постоянными и непостоянными выражениями должна была быть проведена где-то, и авторы языка предпочли сделать это различие относительно простым, с небольшим количеством особых случаев.)
Теперь, конечно, верно, что язык C мог быть определен так, что LATITUDE
является постоянным выражением. Он находится на С++, и я утверждал, что для C используется аналогичное правило. Но в соответствии с текущими правилами C это не означает, что вы не можете использовать LATITUDE
в инициализаторе для статического объекта.
Это также означает, что clang
(компилятор, который, как я понимаю, является тем, который вызывается при вводе gcc
в MacOS), скорее всего, не соответствует требованиям, поскольку он не может диагностировать эту ошибку. В моей собственной системе Linux я обнаружил, что при вызове с -std=c11 -pedantic
gcc 4.7.2 правильно диагностирует ошибку, но clang 3.4 не делает.
За исключением, возможно, этого пункта из раздела 6.6 пункта 10 стандарта ISO C 2011 года (который также существует в стандартах 1990 и 1999 годов):
Реализация может принимать другие формы постоянных выражений.
Можно предположить, что clang принимает LATITUDE
как константное выражение, потому что он использует это разрешение, но тогда я все же ожидал бы хотя бы предупреждения от clang -std=c11 -pedantic -Wall -Wextra
, и его нет.
UPDATE. Когда я скомпилирую следующее:
#include <stdio.h>
const unsigned long long LATITUDE = (long) 3600000;
int main(void) {
switch (0) {
case LATITUDE:
puts("wrong");
break;
default:
puts("ok(?)");
break;
}
}
с clang 3.0 с параметрами -std=c99 -pedantic
, я получаю:
c.c:7:14: warning: expression is not integer constant expression (but is allowed as an extension) [-pedantic]
case LATITUDE:
^~~~~~~~
1 warning generated.
С clang 3.4, предупреждение:
c.c:7:14: warning: expression is not an integer constant expression; folding it to a constant is a GNU extension [-Wgnu-folding-constant]
case LATITUDE:
^~~~~~~~
1 warning generated.
Таким образом, clang признает, что это не постоянное выражение; ошибка в том, что она не предупреждает об объявлении MAX_COORDINATES_NUMBER
.