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

Соответствует ли текущий стандарт C короткому замыканию "&" и "|"?

Есть ли что-нибудь в стандарте C (я предполагаю в данный момент, что C99 + TC1-3 C11), который гарантирует, что & и | не будут закорочены?

Если я пишу:

x = y & foo();

... Я ожидаю, что foo всегда будет вызван, но действительно ли это определено? Теоретически, если запретить стандарт, говорящий иначе, если y содержит 0, оптимизация времени выполнения может пропустить вызов в отсутствие чего-то, говорящего, что это не разрешено. (И аналогично с |, вы могли бы игнорировать правый операнд, если левый операнд был уже включенным. В этом случае даже x = y * foo(); может быть закорочен, если y были 0.)

Не зная спецификации хорошо (и я этого не делаю), сложно доказать такой негатив. Я могу противопоставить разделы на & (6.5.10 на C99) и && (6.5.13 на C99). В последнем это совершенно ясно:

В отличие от побитового двоичного оператора & оператор && гарантирует оценку слева направо; после оценки первого операнда есть точка последовательности. Если первый операнд сравнивается с 0, второй операнд не оценивается.

... но 6.5.10 конкретно не указывает отрицательную версию этого.

Мне кажется разумным принять тот факт, что 6.5.10 не определяет точку последовательности, означающую, что foo всегда будет вызван, а реализация, которая не вызвала бы его, была бы нестандартной. Я прав об этом?

4b9b3361

Ответ 1

Мне кажется разумным принять тот факт, что 6.5.10 не определяет точку последовательности, означающую, что foo всегда будет вызван, а реализация, которая не вызвала бы его, была бы нестандартной. Я прав об этом?

Да и нет. Действительно, реализация, которая не вызвала бы foo, была бы нестандартной. Однако он не имеет ничего общего с точками последовательности.

Этот параграф, который будет применяться здесь, будет 5.1.2.3/3:

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

Ответ 2

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

Единственными операторами в языке C, которые не определены (все) их операнды, являются ?:, &&, || и sizeof. Единственным способом реализации короткого замыкания | или & является определение (1) того, что значение одного операнда достаточно для того, чтобы знать результат, или, по крайней мере, знать, равен ли результат нулю или отличен от нуля, когда результат используется только как значение истины, и (2), что другой операнд не имеет побочных эффектов, и, следовательно, поведение, не оценивающее его, такое же, как если бы оно было оценено.

При вызове функции маловероятно, что компилятор может определить, что он не имеет побочных эффектов, если он не имеет значения static или помечен как атрибут, специфичный для компилятора, такой как gcc __attribute__((const)).

Изменить: От C99, 5.1.2.3:

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

Операторы, которые не оценивают свои операнды, затем явно документируются как таковые.

Ответ 3

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

(C11, 5.1.2.3p4) "В абстрактной машине все выражения оцениваются в соответствии с семантикой. Фактическая реализация не должна оценивать часть выражения, если она может вывести, что ее значение не используется, и что нет (включая любые вызванные вызовом функции или доступом к летучем объекту).

Понятие наблюдаемого поведения добавляется и уточняется в C11:

(C11, 5.1.2.3p6) "Наименьшие требования к соответствующей реализации: - Доступ к неустойчивым объектам оценивается строго в соответствии с правилами абстрактного машина. - При завершении программы все данные, записанные в файлы, должны быть идентичны результату, который выполнение программы в соответствии с абстрактной семантикой. - Динамика входных и выходных сигналов интерактивных устройств должна иметь место, как указано в 7.21.3. Цель этих требований состоит в том, что небуферизованный или строковый буфер появиться как можно скорее, чтобы убедиться, что подсказки действительно появляются до программа, ожидающая ввода. Это наблюдаемое поведение программы.

Ответ 4

§6.5.10 Оператор побитового И

...

Семантика

3 Обычные арифметические преобразования выполняются в операндах.

Там у вас есть. Применение обычных арифметических преобразований требует, чтобы оба операнда оценивались. Обратите внимание, что этот абзац отсутствует в описании семантики &&, || или ?:.