C-запятая

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

Например,

int a = (10,20) ;

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

Ответы

Ответ 1

Раздел 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 делает различие между трансляцией (временем компиляции) и среды выполнения (run-time).

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

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

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

Ответ 2

ISO/IEC 9899: 1999 6.6/3 (константные выражения) гласит, что в выражениях константы не должны быть запятые (если только часть подвыражения не оценивается), поэтому (10,20) не является постоянным выражением определение.

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

Ответ 3

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

Ответ 4

gcс принимает следующее:

int a = (10,20) ;

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

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