使用不同的格式说明符打印 short int

4
请看这段代码:
#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语言中,当变量被提升时,它的值保持不变。
2个回答

6

s 被转换成了一个 int,这里是一个 4 字节的类型。在所有三种情况下都会发生这种情况。在前两种情况中,printf() 希望得到一个 int,因为格式说明符是希望传递一个 int 类型的。但是在最后一种情况中,你提供了一个格式说明符,它期望一个 8 字节的类型。

这将调用未定义的行为。

在你的情况下,它似乎已经读取了值的上半部分的零值,有效地将已经符号扩展为32位的值零扩展为64位。然而,你不能依赖于这样做的结果 - 它可能正在读取未一致初始化的内存或寄存器。明天它可能就变了。

参数的提升不依赖于格式字符串 - 你必须始终确保传递正确的参数以匹配你指定的格式。所以一个 int 不会被提升为 long。你需要自己进行转换。

一个聪明的编译器应该会给你一个警告。


在第二种情况下,s只是被晋升为int,那么为什么最后一种情况没有呢?好吧,在第2种情况下,我提供了一个格式说明符,它期望一个4字节类型,但是问题很快就通过迅速将s提升为int来解决了。第三种情况也可以这样做。但是没有。为什么呢? - rootkea
它已将其提升为int。但是该函数尝试读取一个不同大小的long。我已经尝试添加了一些澄清,以解释可能导致您看到的结果的原因。 - JasonD
谢谢!你的意思是无论参数类型如何,每当调用printf时,参数都会被提升为int类型?那么格式说明符在这里起什么作用呢? - rootkea
正如我在答案中所说,格式字符串不会影响提升。短整型始终以相同的方式进行提升。如果您仔细想一想,格式字符串可能是在运行时生成的 - 在这种情况下,编译器无法知道如何提升参数。因此规则是预先固定的。 - JasonD

1
变量在调用 printf("s = %ld\n", s); 时不会提升为 long 类型。正确的提升方式是使用 printf("s = %ld\n", (long) s);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接