Печать короткого int с использованием различных спецификаторов формата

Пожалуйста, взгляните на этот код:

#include <stdio.h>
int main(void)
{
short s = -1;

printf("sizeof(short) = %lu\n", sizeof(short));
printf("sizeof(int) = %lu\n", sizeof(int));
printf("sizeof(long) = %lu\n", sizeof(long));
printf("s = %hd\n", s);
printf("s = %d\n", s);
printf("s = %ld\n", s);

return 0;
}  

Он дал вывод как:

sizeof(short) = 2  
sizeof(int) = 4  
sizeof(long) = 8  
s = -1  
s = -1  
s = 4294967295  

В последней строке, почему s = 4294967295 вместо s = -1, как через этот вопрос, я узнал, что в C, когда переменная получает повышение, ее значение остается постоянным.


person rootkea    schedule 07.02.2013    source источник


Ответы (2)


s преобразуется в int, который здесь является 4-байтовым типом. Это происходит во всех 3-х случаях. В первых двух int — это то, что ожидает printf(), поскольку спецификатор формата предназначен для типа, который будет передан как int. Однако в последнем случае вы указали спецификатор формата, который ожидает 8-байтовый тип.

Это вызывает неопределенное поведение.

В вашем случае похоже, он считывает нули в старших байтах значения, эффективно расширяя до 64 бит значение, которое уже было расширено по знаку до 32 бит. Однако вы не можете зависеть от результатов этого - это может быть чтение памяти или регистр, который не всегда инициализирован. Завтра все может быть иначе.

Продвижение аргументов не зависит от строки формата — вы всегда должны убедиться, что вы передаете правильные аргументы для указанного вами формата. Таким образом, int не будет повышен до long. Вам нужно конвертировать его самостоятельно.

Умный компилятор должен предупредить вас об этом.

person JasonD    schedule 07.02.2013
comment
Во втором случае s просто повышается до int, тогда почему бы и нет в последнем случае? Что ж, в случае 2 я дал спецификатор формата, который ожидает 4-байтовый тип, но затем проблема решается быстрым преобразованием s в int. То же самое можно сделать и в 3-м случае. Но это не так. Почему? - person rootkea; 07.02.2013
comment
Он превратил его в тип int. Однако функция пытается прочитать длинное значение другого размера. Я попытался добавить разъяснение того, что, вероятно, происходит для получения результата, который вы видите. - person JasonD; 07.02.2013
comment
Спасибо! Итак, вы имеете в виду, что всякий раз, когда вызывается printf, аргумент повышается до типа int независимо от типа аргумента? И где в это вписывается спецификатор формата? - person rootkea; 07.02.2013
comment
Как я сказал в своем ответе, строка формата не влияет на продвижение. Короткометражка всегда будет продвигаться одинаково. Если вы думаете об этом, строка формата может быть сгенерирована во время выполнения - и в этом случае компилятор не может знать, как продвигать аргументы. Так что правила устанавливаются заранее. - person JasonD; 07.02.2013

Переменная не становится длинной при вызове printf("s = %ld\n", s);. Правильный способ продвигать его в лонг — это printf("s = %ld\n", (long) s);.

person Sergej Christoforov    schedule 07.02.2013