Непоследовательные результаты от printf с long long int? - PullRequest
1 голос
/ 17 ноября 2009
struct DummyStruct{
        unsigned long long std;
        int type;
};

DummyStruct d;
d.std = 100;
d.type = 10;

/// buggy printf, unsigned long long to int conversion is buggy.
printf("%d,%d\n",d.std, d.type);  // OUTPUT: 0,100 
printf("%d,%d\n", d.type, d.std); // OUTPUT: 10,100 
printf("%lld,%d\n",d.std, d.type); // OUTPUT: 100,10

Пожалуйста, скажите мне, почему преобразование unsigned long long в int неправильно обрабатывается в printf. Я использую glibc.

Это ошибка в printf?

почему printf не выполняет внутреннее преобразование типов?

Ответы [ 4 ]

13 голосов
/ 17 ноября 2009

Аргумент %d сообщает printf to , интерпретировать соответствующий аргумент как int. Попробуйте использовать %llu для long long. И запомните эту справочную карточку .

(так что нет, это не ошибка)

5 голосов
/ 17 ноября 2009

Правило первое: шансы найти ошибку в библиотеке или компиляторе очень и очень малы. Всегда предполагайте, что компилятор / библиотека верны.

Параметры передаются в printf() через механизмы в <stdarg.h> (списки переменных аргументов), что подразумевает некоторую магию в стеке.

Не вдаваясь в подробности, printf() делает , предполагая , что следующий параметр, который он должен извлечь из стека, имеет тип, указанный в вашей строке формата - в случае %d, подписано int .

Это работает, если фактическое значение, которое вы ввели, меньше или равно по ширине int, потому что внутренне любое меньшее значение, передаваемое в стеке, расширяется до ширины int через механизм под названием " целочисленное продвижение ".

Это не удастся, однако, если тип, который вы передали printf(), на больше , чем int: printf() говорит (вашим %d) ожидать int, и извлекает из стека соответствующее количество байтов (предположим, 4 байта для 32-битного int).

В случае вашего long long, который мы предполагаем равным 8 байтам для 64-битного значения, это приводит к printf() получению только половины вашего long long. Остальное все еще находится в стеке и даст довольно странные результаты, если вы добавите еще %d в строку формата.

; -)

5 голосов
/ 17 ноября 2009

Проблема в вашем использовании. Если типы, указанные в строке формата, не совпадают с типами в параметрах, то все будет работать некорректно.

Это потому, что компилятор помещает параметры как есть в стек.
Там нет проверки типа или преобразования.

Во время выполнения код извлекает значения из стека и перемещается к следующему объекту на основе значения в строке формата. Если строка формата неверна, то полученная сумма неверна, и вы получите забавные результаты.

1 голос
/ 17 ноября 2009

При использовании printf (которая является одной из самых старых функций из оригинального C) компилятор не приводит параметры после списка форматирования к нужному типу, т.е. вам нужно убедиться, что типы в списке параметров соответствуют один в формате.

В большинстве других функций компилятор сжимает данный параметр в объявленные типы, но printf, scanf и friends требуют you , чтобы сообщить компилятору, какие именно типы следуют.

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