Главное отличие, которое еще никто не упомянул, состоит в том, что до ANSI C определялся в основном прецедентом, а не спецификацией; в тех случаях, когда определенные операции будут иметь предсказуемые последствия на некоторых платформах, но не на других (например, использование реляционных операторов на двух несвязанных указателях), прецедент настоятельно способствовал предоставлению программисту гарантий платформы. Например:
На платформах, которые определяют естественное ранжирование среди всех указателей на все объекты, применение реляционных операторов к произвольным указателям может быть использовано для получения этого ранжирования.
На платформах, где естественные средства проверки того, является ли один указатель «больше» другого, никогда не имеют побочного эффекта, кроме получения значения true или false, применение реляционных операторов к произвольным указателям также можно полагаться никогда не иметь побочных эффектов, кроме получения истинного или ложного значения.
На платформах, где два или более целочисленных типа имеют один и тот же размер и представление, можно полагаться на указатель на любой такой целочисленный тип для чтения или записи информации любого другого типа с тем же представлением.
На платформах с двумя дополнительными компонентами, где целочисленные переполнения естественным образом переносятся молча, можно полагаться на то, что операция, включающая в себя значения без знака, меньшие, чем «int», будет вести себя так, как если бы значение было без знака в тех случаях, когда результат находился бы между INT_MAX + 1u и UINT_MAX, и он не был переведен в более крупный тип, ни в качестве левого операнда >>
, ни в качестве операнда /
, %
, ни в какой-либо оператор сравнения. Между прочим, обоснование Стандарта дает это как одну из причин, по которой мелкие беззнаковые типы продвигаются к подписанному .
До C89 было неясно, на какие длины компиляторы для платформ, где вышеперечисленные предположения не будут естественным образом рассчитывать, все равно будут поддерживать эти предположения, но было мало сомнений в том, что компиляторы для платформ, которые могли бы легко и дешево Отстаивать такие предположения следует так. Авторы Стандарта С89 не удосужились прямо сказать это, потому что:
Компиляторы, чьи авторы не были намеренно тупыми, продолжали бы делать такие вещи, когда это практично, без необходимости объяснения (обоснование, приведенное для продвижения небольших значений без знака для подписи, сильно подкрепляет эту точку зрения).
Стандарт только требовал, чтобы реализации были способны запускать одну, возможно, изобретенную программу без переполнения стека, и признал, что в то время как тупая реализация может обрабатывать любую другую программу как вызывающую Undefined Behavior, но не считает, что это стоит беспокоиться о тупых авторах компиляторов, пишущих реализации, которые «соответствуют», но бесполезны.
Хотя «C89» одновременно интерпретировалось как означающее «язык, определенный C89, плюс все дополнительные функции и гарантии, предоставляемые платформой», авторы gcc выдвигают интерпретацию, которая исключает любые функции и гарантии, помимо тех, которые предусмотрены C89 .