short类型变量自动扩展为整数类型?

时间:2009-12-05 14:11:41

标签: c

我想打印b [FFFC]的值,如下所示,

short var = 0xFFFC;
printf("%d\n", b[var]);

但它实际上打印了b [FFFF FFFC]的值。

为什么会这样?

我的电脑由Windows XP以32位架构运行。

6 个答案:

答案 0 :(得分:7)

short是签名类型。它的实现是16位。 0xFFFC表示整数常量65,532,但转换为16位有符号值时,结果为-4。

因此,您的行short var = 0xFFFC;将var设置为-4(在您的实现上)。

0xFFFFFFFC是-4的32位表示。所有发生的事情是您的值正在从一种类型转换为更大的类型,以便将其用作数组索引。它保留了它的值,即-4。

如果您确实想要访问数组的65,533rd元素,那么您应该:

  • var使用更大的类型。 int在32位Windows上就足够了,但总的来说size_t是一个无符号类型,对于非负数组索引来说,它的保证足够大。
  • 使用unsigned short,其中 为此示例提供足够的空间,但如果您想再向前迈进4步,则会出错。

答案 1 :(得分:1)

在当前编译器中,如果写short使用32位,则不能使用short(16位)。
例如,我在Ubuntu Linux 32位中用gcc4编译相同的代码:

int main(int argc, char** argv)
{
    short var = 0xFFFC;
    printf("%x\n", var);
    printf("%d\n", var);
    return (EXIT_SUCCESS);
}

,输出为:

fffffffc
-4

你可以看到强制转换为32位正常,并在2的补码中使用符号扩展

答案 2 :(得分:1)

使用%hx 或%hd来表示您有一个短变量,例如:

  printf("short hex: %hx\n", var);     /* tell printf that var is short and print out as hex */

编辑:Uups,我的问题出错了。我认为这不是关于printf()的。所以这个答案可能有点OT。

:因为您使用 var 作为数组的索引,所以您应该将其声明为 unsigned short (而不是short):

unsigned short var = 0xFFFC;
printf("%d\n", b[var]);

'short var'可以解释为负数。

更确切地说:

您正在“下溢”到负值范围:从0x0000到0x7FFF范围内的值将是正常的。但是从0x8000到0xFFFF的值将为负值。

以下是 var 的一些示例,用作数组b []的索引:

short var=0x0000;; // leads to b[0]        => OK
short var=0x0001;  // leads to b[1]        => OK
short var=0x7FFF;  // leads to b[32767]    => OK
short var=0x8000;  // leads to b[-32768]   => Wrong
short var=0xFFFC;  // leads to b[-4]       => Wrong

short var=32767;   // leads to the same as b[0x7FFF]   => OK
short var=32768;   // compile warning or error => overflow into 32bit range

答案 3 :(得分:1)

作为可用的C数据类型的复习,请查看here。 有一个规则,它涉及C的用法,一些数据类型被提升为它们的整数类型,例如

char ch = '2';
int j = ch + 1;

现在查看表达式的RHS(右侧)并注意ch将自动升级为 int ,以便在LHS上产生所需的结果( LHS)的表达方式。 j的价值是多少? '2'的ASCII码为50十进制或0x32十六进制,加1为1,j的值为51十进制或0x33十六进制。

理解该规则很重要,这解释了为什么数据类型会“被提升”为另一种数据类型。

什么是b?这是一个我认为655532元素正确的数组吗?

无论如何,使用格式说明符%d的类型为int,值首先被提升为int,其次,数组下标的类型为int,因此使用{ {1}}得到提升,因为int的数据大小是4个字节,所以它被提升了,因此你看到了剩余的值0xFFFF 0xFFFC。

这是使用 cast 的地方,告诉编译器将强制数据类型告诉另一个,这与Gregory Pakosz上面的答案一起解释。

希望这有帮助, 最好的祝福, 汤姆。

答案 4 :(得分:0)

你期望在32位对齐的内存中存储一​​个16位变量...你看,每个内存地址都有一个整个 32位字(硬件)。

额外的FFFF来自short是签名值的事实,当分配给 int (在printf调用时)时,它得到了签名扩展。当将两个补码从16位扩展到32位时,通过将最后N位复制到其左侧的所有其他M-N来完成扩展。当然,你并不打算这样做。

因此,在这种情况下,您对绝对数组位置感兴趣,因此您应该将索引器声明为 unsigned

答案 5 :(得分:0)

在您的问题的主题中,您已经猜到了这里发生了什么:是的,类型short的值被“自动扩展”为类型int的值。此过程称为整数提升。这就是它总是在C语言中工作的方式:每次使用小于int的整数值时,该值总是被隐式提升为int类型的值(无符号值可以提升为unsigned int })。当然,值本身不会改变,只会改变值的类型。在上面的示例中,模式short表示的16位0xFFFC值与模式int表示的32位0xFFFFFFFC值相同,即{{1}小数点。这个,BTW,使你的问题的其余部分听起来很奇怪:促销与否,你的代码试图访问-4。促销b[-4]不会改变任何内容。