C中的Tilde算子

时间:2014-11-25 14:23:02

标签: c int unsigned short

 unsigned short int i = 0;
 printf("%u\n",~i);

为什么此代码在控制台中返回32位数字?它应该是16位,因为short是2个字节。

输出为4,294,967,295,应为65,535。

4 个答案:

答案 0 :(得分:5)

%u期待unsigned int;如果您要打印unsigned short int,请使用%hu

修改

Lundin是正确的,~i在转移到int之前会转换为printf类型。由于传递给可变函数,i也会转换为int。但是,如果使用printf转换说明符,unsigned short会在打印前将参数转换回%hu

7.21.6.1 fprintf功能
...
3格式应为多字节字符序列,以其首字母开头和结尾 转移状态。格式由零个或多个指令组成:普通的多字节 字符(不是%),不加改变地复制到输出流;和转换 规范,每个规范导致获取零个或多个后续参数, 根据相应的转换说明符转换它们(如果适用),以及 然后将结果写入输出流 ...
7长度修饰符及其含义如下:
...
h指定以下diouxX转换说明符适用于 short intunsigned short int参数(参数将会 已根据整数促销推广,但其价值应为 在打印前转换为short intunsigned short int ); 或者以下n转换说明符适用于指向short int参数的指针。

强调我的。

所以,行为未定义;如果i~i不是整数类型,则只会是未定义的。

答案 1 :(得分:4)

当您将参数传递给printf且该参数的整数类型短于int时,根据K& R参数提升规则将其隐式提升为int。因此,您的printf - 调用实际上就像:

printf("%u\n", (int)~i);

请注意,这是未定义的行为,因为您告诉printf该参数具有unsigned类型,而int实际上是签名类型。将i转换为unsigned short然后转换为unsigned以解决未定义的行为和您的问题:

printf("%u\n", (unsigned)(unsigned short)~i);

答案 2 :(得分:4)

N1570 6.5.3.3一元算术运算符p4:

  

〜运算符的结果是其(提升的)操作数的按位补码(即,   当且仅当转换后的操作数中的相应位为时,才会设置结果中的每个位   没有设置)。 对操作数执行整数提升,结果为   推广类型。 ......

小于int的整数类型将提升为int。如果sizeof(unsigned short) == 2sizeof(int) == 4,则结果类型为int

还有,printf转换说明符%u需要unsigned int,因此int的表示形式被解释为unsigned int。你基本上对编译器撒谎,这是未定义的行为。

答案 3 :(得分:3)

这是因为printf()的参数是用文字放入堆栈的,因为printf内部无法知道参数是否很短。同样通过使用%u格式,您只是声明您传递的是无符号数字。