Оператор с запятой - PullRequest
15 голосов
/ 15 ноября 2009

Почему выражение, указанное внутри оператора запятой (например, в приведенном ниже примере), не считается константным выражением?

Например,

int a = (10,20) ;

при задании в глобальной области видимости выдает ошибку «инициализатор не является константой», хотя оба выражения, разделенные запятыми, являются константами (константными выражениями). Почему все выражение не рассматривается как постоянное выражение? Для пояснения я прочитал Что делает оператор ‘,’ в C? и Использование оператора запятой C . Они не рассматривали этот аспект оператора запятой.

Ответы [ 4 ]

33 голосов
/ 15 ноября 2009

Раздел 6.6/3, "Постоянные выражения" стандарта ISO C99 - это нужный вам раздел. В нем говорится:

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

В обосновании C99 от ISO есть небольшой фрагмент:

Целочисленное константное выражение должно включать только числа, известные во время перевода, и операторы без побочных эффектов.

И, поскольку вообще нет смысла использовать оператор запятой , если вы не полагаетесь на побочные эффекты, это бесполезно в постоянном выражении.

Под этим я подразумеваю, что нет абсолютно никакой разницы между двумя сегментами кода:

while (10, 1) { ... }
while     (1) { ... }

, поскольку 10 на самом деле ничего не делает . На самом деле

10;

- совершенно правильное, хотя и не очень полезное утверждение C, которое большинство людей не понимают, пока не узнают язык лучше.

Однако, есть разница между этими двумя утверждениями:

while (  10, 1) { ... }
while (x=10, 1) { ... }

В последнем использовании оператора запятой есть побочный эффект, который устанавливает переменную x в 10.

Что касается того, почему им не нравятся побочные эффекты в константных выражениях, весь смысл константных выражений заключается в том, что их можно оценивать во время компиляции, не требуя среды выполнения - в ISO делается различие между переводом (время компиляции) и среды выполнения (во время выполнения).

Понятие о том, почему ISO решила не требовать от компиляторов предоставления информации о среде выполнения (кроме материалов, содержащихся в заголовочных файлах, таких как limits.h), можно найти чуть позже в обосновании:

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

Другими словами, ISO не хотела, чтобы производители кросс-компиляторов были обременены переносом среды исполнения для каждой возможной цели.

6 голосов
/ 15 ноября 2009

ИСО / МЭК 9899: 1999 6.6 / 3 (константные выражения) гласит, что константные выражения не должны содержать операторов запятой (если только часть подвыражения не оценивается), поэтому (10,20) не является константным выражением определение.

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

0 голосов
/ 15 ноября 2009

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

0 голосов
/ 15 ноября 2009

gcс принимает это:

int a = (10,20) ;

int main() {
  printf("%d\n",a);
}

и печать 20. Возможно это проблема вашего компилятора?

...