有符号/无符号int、short和char
我试图理解以下给出的代码的输出: 在此引用以供参考:有符号/无符号int、short和char,c,printf,integer-promotion,C,Printf,Integer Promotion,我试图理解以下给出的代码的输出: 在此引用以供参考: #include <stdio.h> int main(void){ int l; short s; char c; l = 0xdeadbeef; s = l; c = l; printf("l = 0x%x (%d bits)\n", l, sizeof(l) * 8); printf("s =
#include <stdio.h>
int main(void){
int l;
short s;
char c;
l = 0xdeadbeef;
s = l;
c = l;
printf("l = 0x%x (%d bits)\n", l, sizeof(l) * 8);
printf("s = 0x%x (%d bits)\n", s, sizeof(s) * 8);
printf("c = 0x%x (%d bits)\n", c, sizeof(c) * 8);
return 0;
}
以下是我的理解:-
赋值s=l,c=l将导致s和c被提升为int,并且它们将分别具有l的最后16位(0xbeef)和最后8位(0xef)
Printf尝试将上述每个值(l、s和c)解释为无符号整数(因为%x作为格式说明符传递)。从输出中,我看到符号扩展已经发生。我的疑问是,既然%x表示无符号int,为什么在打印s和c时会发生符号扩展?s的输出不应该是0x0000ef,c的输出不应该是0x000000ef吗
为什么在打印s和c时进行符号扩展
让我们看看下面的代码:
unsigned char ucr8bit; /* Range is 0 to 255 on my machine */
signed char cr8bit; /* Range is -128 to 127 on my machine */
int i32bit;
cr8bit = MINUS_100; /* (char)(-100) or 0x9C */
i32bit = cr8bit; /* i32 bit is -100 or 0xFFFFFF9C */
如您所见,尽管数字-100
相同,但它的表示形式不仅仅是在较宽字符中预加0
s,还可能在system和system中预加有符号的类型的MSB或符号位
在您的示例中,您试图将s
和c
打印为更宽的类型,从而获得符号位复制
此外,您的代码还包含许多未定义和未指定行为的源,因此可能在不同的编译器上提供不同的输出。
(例如,您应该使用signed char
而不是char
,因为char
在某些实现中可能表现为unsigned char
,在某些其他实现中可能表现为signed char
)
您使用的是32位有符号整数。这意味着只有31位可以用于正数。0xdeadbeef使用32位。因此,将其分配给32位有符号整数将使其成为负数
当使用无符号转换说明符%x显示时,它看起来像是负数(带符号扩展名)
将其复制到short或char中时,保留其为负数的属性
要进一步显示这一点,请尝试设置:
l = 0xef;
现在输出为:
l = 0xef (32 bits)
s = 0xef (16 bits)
c = 0xffffffef (8 bits)
0xef使用8位,当放入32位或16位变量时为正。当您将8位数字放入有符号8位变量(char)中时,您正在创建一个负数
要查看负数的保留,请尝试反向操作:
c = 0xef;
s = c;
l = c;
输出为:
l = 0xffffffef (32 bits)
s = 0xffffffef (16 bits)
c = 0xffffffef (8 bits)
标志延伸发生在推送过程中,而不是打印过程中。您的任务是由实现定义的。如果一个值对于一个有符号的目标类型是不可表示的,那么实现将接管它。不要依赖于观察到的行为(尽管位截断确实是我见过的最常见的行为)。printf
是一个可变函数,这意味着调用函数时,short
和char
类型的参数被提升为int
。sizeof
返回size\u t
,若要打印必须使用的size\u t
,并且一个字节并不总是有8位,请改用char\u BIT
“作业s=l
和c=l
将导致s
和c
被提升为int
”-更像“将导致l
被截断为short
和char
“。如果short
和char
始终升级为int
,则printf(“%x”,someShortValue))
在各个方面都必须与printf(“%x”,(int)someShortValue)等效代码>,已定义,对吗?@immibis这两个都会导致未定义的行为%x
只能与无符号int
一起使用。将%x
与int
的非负值一起使用;或者更小的值被提升为非负值int
,这在技术上是未定义的行为,但大多数人似乎认为该标准在该领域存在缺陷,实际上,我们将其视为它确实允许这样做。
c = 0xef;
s = c;
l = c;
l = 0xffffffef (32 bits)
s = 0xffffffef (16 bits)
c = 0xffffffef (8 bits)