Раздел 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 не хотела, чтобы производители кросс-компиляторов были обременены переносом среды исполнения для каждой возможной цели.