Детали того, что составляет постоянное выражение в C? - PullRequest
9 голосов
/ 04 февраля 2011

C определяет как минимум 3 уровня «константного выражения»:

  • константное выражение (неквалифицированное)
  • выражение арифметической константы
  • целочисленное константное выражение

6,6, пункт 3 гласит:

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

Значит ли это, что 1,2 не является константным выражением?

Пункт 8 гласит:

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

Какие операнды в (union { uint32_t i; float f; }){ 1 }.f? Если 1 является операндом, то это, вероятно, выражение арифметической константы, но если { 1 } является операндом, то это явно не так.

Редактировать: Еще одно интересное наблюдение: 7.17, параграф 3 требует, чтобы результатом offsetof было целочисленное константное выражение типа size_t, но стандартными реализациями offsetof, насколько я можете сказать, по стандарту не обязательно быть целочисленными константными выражениями. Это, конечно, хорошо, так как реализации разрешено (в соответствии с пунктом 6.6) принимать другие формы константных выражений или реализовывать макрос offsetof как __builtin_offsetof, а не посредством вычитания указателя. Суть этого наблюдения, однако, заключается в том, что если вы хотите использовать offsetof в контексте, где требуется целочисленное константное выражение, вам действительно нужно использовать макрос, предоставленный реализацией, а не бросать свой собственный.

Ответы [ 2 ]

2 голосов
/ 04 февраля 2011

Исходя из вашего чтения, 1,2 не является константным выражением.Я не знаю, почему это не так, просто я согласен с вами, что это не так (несмотря на то, что, вероятно, так и должно быть).

6.5.2 определяет составные литералы в качестве постфиксного оператора.Так что в

(union { uint32_t i; float f; }){ 1 }.f

операндами являются (union { uint32_t i; float f; }){ 1 } и f для оператора ..Это не арифметическое константное выражение, поскольку первый аргумент имеет тип union, но это константное выражение.

ОБНОВЛЕНИЕ: Я основывал это на другой интерпретациистандарт.

Мои предыдущие рассуждения заключались в том, что (union { uint32_t i; float f; }){ 1 }.f удовлетворял критериям постоянного выражения и поэтому являлся постоянным выражением.Я все еще думаю, что оно соответствует критериям для постоянного выражения (пункт 6.6 пункта 6), но это не какой-либо из стандартных типов постоянных выражений (целочисленное, арифметическое или адресное) и поэтому является предметом постоянного выражения только в пункте 6.6.10, которая допускает определяемые реализацией константные выражения.

Я также хотел получить ваше редактирование.Я собирался утверждать, что «взломанная» реализация offsetof была константным выражением, но я думаю, что это то же самое, что и выше: оно соответствует критериям для константного выражения (и, возможно, адресной константы), но не является целочисленной константой.выражение, и, следовательно, является недействительным за пределами 6.6 пункта 10.

0 голосов
/ 04 февраля 2011

Если бы 1,2 было бы константным выражением, это позволило бы скомпилировать такой код:

{ // code        // How the compiler interprets:
  int a[10, 10]; // int a[10];

  a[5, 8] = 42;  // a[8] = 42;
}

Я не знаю, является ли это реальной причиной, но я могу представить, что испусканиеошибка для этой (распространенной?) ошибки считалась более важной, чем превращение 1,2 в константное выражение.

ОБНОВЛЕНИЕ : Как указывает Р. в комментарии, код о небольше ошибка компилятора с момента появления VLA.

...