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) принимать другие формы константных выражений, или реализовать макрос смещения
как __ builtin_offsetof
, а не через вычитание указателя. Однако суть этого наблюдения заключается в том, что если вы хотите использовать offsetof
в контексте, где требуется целочисленное постоянное выражение, вам действительно нужно использовать макрос, предоставленный реализацией, а не использовать собственный.