По какой-то причине возник миф о том, что авторы Стандарта использовали фразу «неопределенное поведение» для описания действий, которые ранние описания языка его изобретателем характеризовали как «машинно-зависимые», позволяли компиляторам выводить, что различные ничего бы не случилось. Хотя это правда, что Стандарт не требует, чтобы реализации обрабатывали такие действия осмысленно даже на платформах, где было бы естественное «машинно-зависимое» поведение, Стандарт также не требует, чтобы любая реализация была способна обрабатывать любые полезные программы осмысленно; реализация могла бы соответствовать, не имея возможности осмысленно обрабатывать что-либо, кроме одной придуманной и бесполезной программы. Это не противоречит намерению Стандарта: «Несмотря на то, что несовершенная реализация, вероятно, могла бы создать программу, которая удовлетворяет этому требованию, но все же может быть бесполезной, Комитет C89 считал, что такая изобретательность, вероятно, потребует больше работы, чем что-то полезное».
Обсуждая решение о том, чтобы короткие значения без знака повышались до подписанного int, авторы Стандарта отметили, что в большинстве современных реализаций используется семантика тихого переноса целочисленного переполнения, и если значения, повышающие до целого числа int, не будут отрицательно влиять на поведение, если значение использовалось в сценарии переполнения ios, где верхние биты не имели бы значения.
С практической точки зрения гарантирование чистой семантики циклического переноса стоит немного больше, чем если бы целочисленные вычисления вели себя так, как если бы они выполнялись на больших блоках. типы в неуказанные времена. Даже в отсутствие «оптимизации» даже прямое генерирование кода для выражения, подобного long1 = int1*int2+long2;
, на многих платформах выиграло бы от возможности использовать результат команды умножения 16x16-> 32 или 32x32-> 64 напрямую, вместо того, чтобы иметь подписать-расширить нижнюю половину результата. Кроме того, разрешение компилятору оценивать x+1
как тип, больший, чем x, при его удобстве позволит ему заменить x+1 > y
на x >= y
- как правило, полезная и безопасная оптимизация.
Компиляторы, такие как g cc go дальше, однако. Хотя авторы Стандарта отметили, что при оценке чего-то вроде:
unsigned mul(unsigned short x, unsigned short y) { return x*y; }
решение Стандарта о продвижении x
и y
до подписано int
не будет t отрицательно влияет на поведение по сравнению с использованием unsigned
(«Обе схемы дают одинаковый ответ в подавляющем большинстве случаев, и обе дают одинаковый эффективный результат в еще большем числе случаев в реализациях с арифметикой с двумя дополнениями c и тихим переходом на переполнение со знаком, то есть в большинстве текущих реализаций. ") g cc иногда будет использовать вышеупомянутую функцию для вывода в вызова, вызывая код, который x
не может превышать INT_MAX/y
. Я не видел доказательств того, что авторы Стандарта ожидали такого поведения, а тем более намеревались его поощрить. Хотя авторы g cc утверждают, что любой код, который вызвал бы переполнение в таких случаях, "не работает", я не думаю, что авторы стандарта согласятся с этим, поскольку при обсуждении соответствия они отмечают: "Цель состоит в том, чтобы дать у программиста есть реальный шанс создать мощные C программы, которые также являются очень переносимыми, и при этом они не кажутся совершенно полезными C программами, которые оказываются не переносимыми, а значит, и наречиями строго. "
Потому что авторы стандарта не удалось запретить авторам g cc бессмысленную обработку кода в случае целочисленного переполнения, даже на платформах с тихим циклом, они настаивают на том, что в таких случаях они должны перепрыгнуть через рельсы. Ни один автор компиляторов, который пытался выиграть платящих клиентов, не принял бы такого подхода, но авторы Стандарта не смогли понять, что авторы компиляторов могут ценить ум, а не удовлетворение клиентов.