Вычислительные платформы - наборы аппаратного и программного обеспечения, работающие вместе - определяют, как аргументы должны передаваться функциям.Эта спецификация того, как передаются аргументы, является частью спецификации, обычно называемой двоичным интерфейсом приложения (ABI).
Сведения о том, как должен передаваться аргумент, могут зависеть от нескольких факторов, в том числе:
- его размер,
- его требование выравнивания,
- его основной тип (целое число, число с плавающей точкой, указатель и т. Д.),
- , является ли он агрегатомнекоторого рода, например, структура или объединение, и
- , все ли сведения об аргументе известны во время компиляции.
Средства, с помощью которых должен передаваться аргумент, могутвключают в себя:
- передается ли он в регистре, в стеке или в памяти,
- , как он выровнен в памяти, и
- , какой наборрегистр процессора передается.
Выражение 3 / 2
имеет тип int
.Он будет передан способом, который ABI указывает для аргумента int
.Когда вы указываете %f
в формате printf
, printf
ожидает double
, а printf
ищет аргумент в месте, которое ABI указывает для double
.
Таким образом,в printf("%f" , 3 / 2);
нет никакой гарантии, что printf
даже увидит переданное значение int
.Он может получать данные из неправильной памяти или регистрироваться полностью.
Если printf
действительно получает данные для значения int
, он будет интерпретировать эти байты, как если бы они были значением double
.Значения байтов имеют другое значение, когда они кодируют int
, чем когда они кодируют double
.Таким образом, значения в байтах, которые кодируют значение int
1, не кодируют 1, когда они кодируют значение double
.Таким образом, даже если printf
, когда он форматирует double
для %f
, получает байты для значения int
, равного 1, производимые им символы вряд ли будут равны «1».
Стандарт C определяет, как вы должны использовать printf
и его спецификаторы формата, чтобы ABI мог работать.Когда вы нарушаете правила C о сопоставлении типов аргументов со спецификаторами формата, стандарт C не определяет, какое поведение приводит к результатам.Это оставляет вас во власти реализации C.Исторически это означало, что вы нарушали ABI, и программа ломалась по причинам, которые я описал выше.Со временем компиляторы стали более агрессивно относиться к оптимизации и другим преобразованиям программ, в результате чего нарушение правил стандарта C может изменить поведение программы более удивительным образом.