Целочисленные и Float деления в C - PullRequest
0 голосов
/ 28 января 2019

Может ли кто-нибудь сказать мне, почему это происходит ..... Я скомпилировал и выполнил его с помощью новейшего компилятора GCC.

Пожалуйста, не давайте предложений, таких как "место% f вместо% d" ии т.д ..

#include <stdio.h>

int main(void)
{
    printf("%d" , 3.0 / 2.0);
    return 0;
}

Ожидаемый результат: 1

Дает результат: 0

#include <stdio.h>

int main(void)
{
    printf("%f" , 3 / 2);
    return 0;
}

Ожидаемый результат: 1.000000

Дает результат: 0.000000

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Вычислительные платформы - наборы аппаратного и программного обеспечения, работающие вместе - определяют, как аргументы должны передаваться функциям.Эта спецификация того, как передаются аргументы, является частью спецификации, обычно называемой двоичным интерфейсом приложения (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 может изменить поведение программы более удивительным образом.

0 голосов
/ 28 января 2019

В первом случае вы передаете выражение типа double, когда спецификатор формата ожидает int, а во втором случае вы передаете выражение типа int, когда спецификатор формата ожидает double.

Использование неправильного спецификатора формата вызывает неопределенное поведение в соответствии со стандартом C, что означает, что вы не можете надежно предсказать, как ваша программа будет вести себя.Разные компиляторы могут проявлять неопределенное поведение по-разному, а также разные настройки оптимизации в одном и том же компиляторе.

Попытка объяснить неопределенное поведение не имеет смысла.Просто убедитесь, что ваша программа хорошо себя ведет, что в данном случае означает использование правильного спецификатора формата.

При этом компиляторы для систем x86 обычно передают параметры с плавающей запятой в регистры с плавающей запятой, а целые числа передаются в стеке.,Поэтому, когда printf пытается прочитать параметр заданного типа, он заканчивает тем, что читает тот мусор, который был там, где он искал, потому что фактического параметра там вообще нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...