Компиляторы Unix слишком слабые или MSVC 2005 не хватает хитрости? - PullRequest
3 голосов
/ 27 марта 2012

Я столкнулся с проблемой с некоторым кодом на С, например:

struct SomeType { ...details immaterial... };

static struct SomeType array[] =
{
    { ... },
    ...
    { ... },
};
enum { ARRAY_SIZE = sizeof(array) / sizeof(array[0]) };

Компиляторы Unix (различные версии GCC и компиляторы в AIX и HP-UX) были вполне довольны enum.MSVC 2005 возражал с ошибкой C2056: Illegal Expression.Согласно MSDN это происходит потому, что «выражение было недопустимым из-за предыдущей ошибки».Это была единственная ошибка, о которой сообщалось, что немного удивляет.

Однако мои вопросы таковы:

  1. Правильно ли MSVC 2005 интерпретирует стандарт C89 при запрете enum?
  2. Являются ли компиляторы Unix слишком щедрыми в разрешении этого без предупреждения?
  3. Имеет ли C99 (или C2011) какое-либо различие?
  4. Все еще более поздние версии MSVC все еще возражают противenum?

FWIW: приемлемым решением было изменить enum на:

static int const ARRAY_SIZE = sizeof(array) / sizeof(array[0]);

Устаревшие варианты являются проблематичными

Майкл Берр дал некоторую дополнительную информацию, которая очень ценна, и позволила мне разблокировать проблему.

Скомпилируемый пример (изоморфный фактическим проблемам):

static const char *names[] = { "abc", "def", "ghi" };
enum { NAMES_SIZE = sizeof(names) / sizeof(names[0]) };

static const struct stuff { const char *name; int flags; } array[] =
{
    { "abc", 1 },
    { "def", 2 },
    { "ghi", 3 },
};
enum { ARRAY_SIZE = sizeof(array) / sizeof(array[0]) };

Точная версия MSVC (как указано cl):

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

Это версия, которую, по словам Майкла, работает.

И я нашел причину своей проблемы.(Команды ниже приводят к удалению всей специфической для проекта болтовни - множества параметров / D и / I, которые не нужны для примера кода.) Компиляция с помощью:

cl     /W3 /c /LD /MD /Od aaa.c

И код выше компилируетсяОК.

cl /Zg /W3 /c /LD /MD /Od aaa.c

Сначала выдается предупреждение:

cl : Command line warning D9035 : option 'Zg' has been deprecated and will be removed in a future release

Я скулил о том, что компиляции выполняются с устаревшими опциями в течение года или более, но никто изКоманда, ответственная за этот подпроект, была готова встать и исправить это, и я не должен - кое-что, что должно измениться.

и затем он говорит:

aaa.c(2) : error C2056: illegal expression
aaa.c(10) : error C2056: illegal expression

Таким образом, опция /Zg не только устарела, но и является причиной проблемы в первую очередь.Теперь у меня есть лучшие боеприпасы для людей с!

Спасибо за дополнительную информацию, Майкл.

PS: На странице MSDN о /Zg написано:

Если вы используете опцию /Zg, и ваша программа содержит формальные параметры типа struct, enum или union (или указатели на такие типы), объявление каждого struct, *Тип 1074 * или union должен иметь тег (имя).

Это не совсем точно.В фрагменте примера нет формальных параметров, и значения enum никогда не передавались в функцию.Но без тега на enum ошибка все еще появляется с флагом /Zg.


(Нет; я не особо привязан к MSVC 2005. Группа, в которой я работаю, просто не имеетпока не обновлен до чего-то более позднего. В основном это не влияет на меня. Бывают случаи, например, когда это очень больно. Однажды я пойму, почему другие сборки на Windows, похоже, принимают enum; боюсь, я обнаружу, что этот конкретный субпродукт не соответствует всем остальным и использует более старый компилятор, чем другие продукты.)

Это строго код на языке Си.Тег MSVC является синонимом тега Visual-C ++.

1 Ответ

2 голосов
/ 27 марта 2012

Это, конечно, допустимо в C89 (при условии, что размер результирующего массива представляется как int).

Ограничение в п. 3.5.2.2 на определяющее значение константы перечисления:

Выражение, определяющее значение константы перечисления, должно быть выражением целочисленной константы, значение которого представлено в виде целого числа.

§3.4 описывает выражения интегральной константы:

Ограничения

Выражения констант не должны содержать операторов присваивания, увеличения, уменьшения, вызова функции или запятой, за исключением случаев, когда они содержатся в операнде оператора sizeof.

Каждое выражение константы должно оцениваться как константа, которая находится в диапазоне представимых значений для его типа.

Семантика

Выражение, которое оценивает константу, требуется в нескольких контекстах.Если выражение вычисляется в среде перевода, арифметическая точность и диапазон должны быть как минимум такими же большими, как если бы выражение оценивалось в среде выполнения.

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

...