Подтвердить что ты не робот

Операторы косвенно запрещены (или нет?) При определении целочисленных константных выражений (в C)

В стандартном C (C99/C11) мы имеем так называемые целочисленные константные выражения, которые являются постоянными выражениями, операнды которых являются постоянными целыми числами.

Используется следующее определение:

Стандарт C99, раздел 6.6 (пар. 6):

Целочисленное постоянное выражение) должно иметь целочисленный тип и должно имеют только операнды, которые являются целыми суммами, константами перечисления, символьные константы, sizeof выражения, результаты которых являются целыми константы и плавающие константы, которые являются непосредственными операндами слепки.

Стандарт C99

Это появляется после определения более общего выражения константы.
(Поскольку целочисленное константное выражение определено после выражения константы, я предполагаю, что первое является частным случаем последнего.)

С другой стороны, условные выражения считаются константными выражениями, которые ограничены следующим правилом:

Стандарт C99, раздел 6.6:

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

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

Теперь, если мы применим эти ограничения к целым константным выражениям, мы грубо получаем, что они состоят из условных выражений, ограниченных таким образом, что каждый операнд является целыми/перечисляющими/символьными константами (или плавающей постоянной сразу же предшествует литье), и поэтому нет назначений, приращений, декрементов, функций-вызовов или запятых.

  • В силу простоты предположим, что E является таким выражением без оператора sizeof и без неопытных операндов.

МОЙ ВОПРОС:
Являются ли следующие операторы косвенно запрещенными в E:

  • & (адрес),
  • * (косвенность),
  • [] (индекс массива),
  • . (элемент структуры),
  • -> (указатель на элементы структуры).

Кроме того, запрещены ли составные литералы?

Примечание:. Я заинтересован в ответе на этот вопрос для строгих программ соответствия (C99/C11).

Я думаю, что они не могут быть в любом подвыражении E, но я не уверен, что это полностью верно. Мое быстрое рассуждение таково:

  • Если F является подвыражением целой константы E, то F имеет по определению целочисленный тип T.
  • Если унарный оператор & появляется перед F в E, то & F содержит операнд, имеющий тип "указатель на T", который не разрешен в E (несмотря на то, что F не является объектом, а только целочисленным значением, поэтому & не может применяться). Таким образом, & не может появляться ни в одном E.
  • Так как F не имеет никакого типа указателя, он не имеет смысла выражение *F.
  • Оператор индекса [] используется для указания элемента внутри массива. Это означает, что у нас было бы E нечто вроде A[N]. Здесь N должно быть целочисленным постоянным выражением. Однако мы отмечаем, что A также является операндом, но он является объектом типа array, который не допускается в E. Это означает, что оператор массива-индекса не может отображаться в E.
  • Если у нас есть E операторы . и ->, они подразумевают, что они используются внутри E следующим образом: S.memb pS->memb. Таким образом, мы имеем операнд S, тип которого struct или union и pS, который является pointer to struct or pointer to union. Но эти "операнды" не допускаются в E.
  • Компонентные литералы не допускаются в E, потому что они являются lvalues, что означает, что они будут иметь адрес при запуске программы. Поскольку такой адрес не может быть известен компилятору, выражение, включающее составной литерал, не считается константой.

Считаете ли вы, что мои рассуждения верны?
Знаете ли вы исключительные случаи, что некоторые из этих операторов или выражений могут быть [частью] целочисленного постоянного выражения (как в ограниченном случае, который я обозначил E).

4b9b3361

Ответ 1

ICE должен иметь значения (rvalues ​​на жаргоне) в качестве первичных выражений, которые его составляют, и никаких объектов (lvalues).

Если вы создаете оттуда, чтобы исключить операторы, вы увидите, что

  • ни один из операторов, которым требуется lvalue в качестве операнда, может использоваться (назначение, приращение, декремент, унарный &)

  • ни один из операторов, которые производят lvalue, не может использоваться (unary *, член массива [], member ->)

  • операторы ., которым нужен аргумент struct, так как

    • нет литералов для struct

    • Компонентные литералы являются неправильным, они являются объектами.

    • Запрещены вызовы функций.

Некоторые из этих операторов могут появляться в местах, когда они не оцениваются (или не предполагаются), в частности _Alignof, макроса offsetof и некоторых выражений sizeof.