плавать в неожиданное поведение - PullRequest
0 голосов
/ 18 декабря 2010

Не могли бы вы объяснить поведение этой программы.

int main()
{
  float a = 12.5;
  printf("%d\n", a);
  printf("%d\n", *(int *)&a);
  return 0;
} 

Вы можете проверить код на http://codepad.org/AQRlAzkC
почему идет этот вывод ..

Ответы [ 6 ]

4 голосов
/ 18 декабря 2010

Вы не хотите приводить указатель с плавающей точкой к целочисленному указателю.Числа с плавающей точкой и целые числа не сохраняются одинаково, и если вы сделаете это, преобразование не произойдет, и, таким образом, вы получите мусор, выведенный на экран.Однако, если вы приведете int-значение к значению с плавающей точкой, то компиляция преобразует число с плавающей точкой из его внутреннего типа в целое число для вас.Поэтому вы должны заменить (int *) на (int).

Также, %d для десятичных (целых) значений.То, что вы хотите, это %f, для значений с плавающей запятой, для первого printf.

То, что вы хотите, это:

#include <stdio.h>

int main()
{
  float a = 12.5;
  printf("%f\n", a); //changed %d -> %f
  printf("%d\n", (int)a); //changed *(int *)& -> (int) for proper conversion
  return 0;
} 

проверено здесь: http://codepad.org/QD4kzAC9

2 голосов
/ 18 декабря 2010

Числа с плавающей запятой хранятся в формате IEEE 754 .Когда вы передаете спецификатор формата %d в printf(), вы указываете ему посмотреть на первые sizeof(int) байты, начиная с &a.Ну, в формате IEEE 754 это куча нулей.

Я настоятельно рекомендую вам прочитать Что должен знать каждый компьютерный специалист об арифметике с плавающей точкой

0 голосов
/ 18 декабря 2010

Посмотрим.

  1. Плавания хранятся в формате, определенном в IEEE 754. См. Здесь: http://en.wikipedia.org/wiki/IEEE_754-2008
  2. Примечание: в первой инструкции вы передаете удвоение в число с плавающей точкой. Это будет приведено во время компиляции, но некоторые компиляторы могут жаловаться. Если вы хотите использовать float, добавьте f: float a = 12.5f;
  3. Вы передаете значение с плавающей точкой в ​​аргумент% d. Это не хорошо. Компиляторы могут вести себя по-другому, некоторые могут предупредить вас об этом. Если вы хотите использовать float, используйте% f.
  4. Вы берете целое число в формате IEEE-754 и распечатываете его. См. Ссылку в пункте 1, чтобы увидеть, что вы печатаете.
0 голосов
/ 18 декабря 2010

Приведение указателя и приведение значения - это очень разные операции.Когда вы приводите число с плавающей точкой к типу int, вы запрашиваете преобразование значения с плавающей точкой в ​​значение int, что приводит к фактическому преобразованию данных;когда вы приводите указатель с плавающей точкой к указателю типа int, вы просто отменяете проверки типов.Указатель - это просто целочисленная ячейка памяти: приведение его к другому виду указателя не требует каких-либо преобразований.

Итак, вы видите, как выглядит битовый шаблон вашего числа с плавающей точкой, когда рассматривается как целое число.

Битовые шаблоны, которые большинство компьютеров используют для представления чисел с плавающей запятой, описываются стандартом IEEE-754 .Целые числа, с другой стороны, это просто целые числа, представленные в двоичной базе.Следовательно, взятие битов действительного числа и интерпретация их как целого числа дает совершенно разные результаты.

0 голосов
/ 18 декабря 2010

Разница в том, что в одном случае компилятор выполняет неявное приведение (я предполагаю, что вы получаете 12 из первого), а во втором случае он берет память, содержащую значение с плавающей запятой, и интерпретирует ее как int. Было бы полезно, если бы вы включили фактический результат.

0 голосов
/ 18 декабря 2010

Я думаю, что это печатает 12 12 из-за% d нет разницы и * & a = a

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