Изменяемый массив в области видимости файла - PullRequest
6 голосов
/ 25 января 2011

Что не так со следующим кодом?

#define DELAY_CYCLES ((int)(0.1/0.001))
typedef struct {
    double state_history[N_X][DELAY_CYCLES];
    double foo;
} foo

gcc жалуется:

main.h: 52: 3: предупреждение: изменяемая переменная state_history в области видимости файла

Это потому, что приведение типа int по какой-то причине не может быть выполнено во время компиляции?

Ответы [ 2 ]

11 голосов
/ 25 января 2011

ВНОВЬ РЕДАКТИРОВАТЬ

Если вы следуете стандарту букве, тогда да, вам следует избегать выражений с плавающей точкой.В C, за единственным исключением констант с плавающей точкой, приведенных к целым числам (таким как (int)3.0f), выражения с плавающей точкой не рассматриваются как целочисленные константные выражения во время компиляции с целью вычисления размера массива.Вам нужно изменить определение, чтобы избежать чисел с плавающей запятой и использовать исключительно целые числа.

Чтобы не быть массивом переменной длины, размеры массива должны быть «целочисленными константными выражениями» (C99 §6.7.5.2/ 4), и «целочисленное константное выражение» определено в §6.6 / 6 (выделено мной):

целочисленное константное выражение 96) должен иметь целочисленный тип и иметь только операнды, которые являются целочисленными константами, константами перечисления, символьными константами, sizeof выражениями, результаты которых являются целочисленными константами, и плавающими константами, которые являются непосредственными операндами приведений .Операторы приведения в выражении с целочисленной константой должны преобразовывать только арифметические типы в целочисленные типы, кроме как в качестве части операнда к оператору sizeof.

Похоже, что GCC только добавил это предупреждение в версии 4.5.В 4.4 и ниже он не сообщает о каких-либо предупреждениях для этого кода, даже с -Wall -Wextra -ansi -pedantic.Однако, чтобы быть безопасным и переносимым на 100%, вы должны изменить определение DELAY_CYCLES, чтобы избежать выражений с плавающей точкой.

4 голосов
/ 25 января 2011

Даже если бы это было целочисленное константное выражение, (int)(0.1/0.001) могло бы легко быть либо 99, либо 100, поскольку значения 0.1 и 0.001 не существуют в плавающей запятой. Чтобы определить, какое значение указывает IEEE 754, потребуется проверить оба значения: 0,1 и 0,001, чтобы увидеть, находятся ли они ближе к своим соседям выше или ниже, а затем фактически выполнить деление этих соседей - или просто проверить его в соответствующей системе. Однако это единственное место, где я не хотел бы полагаться на соответствие реализации, чтобы получить правильный ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...