C определяет как минимум 3 уровня «постоянного выражения»:
- постоянное выражение (неквалифицированное)
- арифметическое постоянное выражение
- целочисленное постоянное выражение
6.6 пункт 3 гласит:
Постоянные выражения не должны содержать операторов присваивания, приращения, декремента, вызова функции или запятой, за исключением случаев, когда они содержатся в подвыражении, которое не оценивается.
Значит ли это, что 1,2
не является постоянным выражением?
Пункт 8 гласит:
Выражение арифметической константы должно иметь арифметический тип и иметь только операнды, которые являются целочисленными константами, плавающими константами, константами перечисления, символьными константами и выражениями sizeof. Операторы приведения в выражении арифметической константы должны преобразовывать только арифметические типы в арифметические типы, за исключением части операнда в оператор sizeof, результатом которого является целочисленная константа.
Какие операнды в (union { uint32_t i; float f; }){ 1 }.f
? Если 1
является операндом, то это предположительно арифметическое постоянное выражение, но если { 1 }
является операндом, то это явно не так.
Изменить: Еще одно интересное наблюдение: пункт 3 7.17 требует, чтобы результат offsetof
был целочисленным постоянным выражением типа size_t
, но стандартные реализации offsetof
, насколько я могу судить, не обязательно должны быть целочисленные константные выражения по стандарту. Это, конечно, нормально, поскольку реализации разрешено (в соответствии с параграфом 10 6.6) принимать другие формы константных выражений или реализовывать макрос offsetof
как __builtin_offsetof
, а не через вычитание указателя. Однако суть этого наблюдения заключается в том, что если вы хотите использовать offsetof
в контексте, где требуется целочисленное постоянное выражение, вам действительно нужно использовать макрос, предоставленный реализацией, а не использовать собственный.
1,2
я думаю, что1
- это постоянное выражение, а2
- это непрерывное выражение. - person Pawel Zubrycki   schedule 04.02.20111,2
, в котором используется оператор запятой, который по какой-то причине, которую я не могу объяснить, похоже, был исключен из операторов, разрешенных в постоянных выражениях. - person R.. GitHub STOP HELPING ICE   schedule 04.02.20111,2
- это одно выражение. Он состоит из двух целочисленных литералов,1
и2
, в качестве аргументов запятой operator (6.5.17) для создания одного выражения. Вопрос R .. в том, что если и1
, и2
являются константными выражениями, почему1,2
непостоянное выражение? - person Chris Lutz   schedule 04.02.2011enum {a=(1,2)};
, так иenum {b=(struct {int i;}){1}.i};
. Конечно, это не имеет отношения к стандарту. - person Joseph Quinsey   schedule 04.02.2011(void *)(0,0)
для построения преобразования 0 (какint
) в указатель, что отличается от преобразования целочисленного постоянного выражения 0 в указатель. (последний является нулевым указателем). К сожалению, стандарт допускает дополнительные константные выражения, определяемые реализацией, поэтому я полагаю, что это ненадежно .... - person R.. GitHub STOP HELPING ICE   schedule 26.03.2011(void*)(1-1)
синонимом(void*)0
? - person supercat   schedule 02.09.2014void *
, это будет константа нулевого указателя с известным фиксированным типом (void *
) и, таким образом, синонимом для всех целей, кроме преобразования в строку через препроцессор. :-) - person R.. GitHub STOP HELPING ICE   schedule 02.09.2014