Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 短类型变量是否自动扩展为整数类型?_C - Fatal编程技术网

C 短类型变量是否自动扩展为整数类型?

C 短类型变量是否自动扩展为整数类型?,c,C,我想打印b[FFFC]的值,如下所示 short var = 0xFFFC; printf("%d\n", b[var]); 但它实际上打印了b[FFFF FFFC]的值 为什么会这样 我的计算机由Windows XP以32位体系结构操作。您希望在32位对齐的内存中只存储16位变量。。。您可以看到,每个内存地址都包含一个完整的32位字(硬件) 额外的FFFF来自这样一个事实:short是一个有符号的值,当分配给int时(在printf调用时),它被符号扩展。当将两个补码从16位扩展到32位时,

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

short var = 0xFFFC;
printf("%d\n", b[var]);
但它实际上打印了b[FFFF FFFC]的值

为什么会这样


我的计算机由Windows XP以32位体系结构操作。

您希望在32位对齐的内存中只存储16位变量。。。您可以看到,每个内存地址都包含一个完整的32位字(硬件)

额外的FFFF来自这样一个事实:short是一个有符号的
值,当分配给int时(在printf调用时),它被符号扩展。当将两个补码从16位扩展到32位时,扩展是通过将最后的N位复制到它左边的所有其他M-N来完成的。当然,你不是有意的


因此,在本例中,您对绝对数组位置感兴趣,因此您应该将索引器声明为无符号

在当前编译器中,如果write
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

您可以看到cast short to 32位normal,并在2的补码中使用符号扩展名使用%hx或%hd来表示您有一个短变量,例如:

  printf("short hex: %hx\n", var);     /* tell printf that var is short and print out as hex */
编辑:哎呀,我把问题搞错了。这与我所想的printf()无关。所以这个答案可能有点过分

New:由于您使用var作为数组的索引,因此应将其声明为无符号短(而不是短):

“短期var”可以解释为负数

更准确地说:

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

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

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

作为C可用数据类型的复习,请看一看。 有一条规则与C的使用有关,例如,某些数据类型被提升为其整数类型

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

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

什么是
b
?我想这是一个包含655532个元素的数组,对吗

无论如何,使用格式说明符
%d
表示int类型,首先将值提升为int,其次将数组下标提升为int类型
int
,因此提升了
short var
的使用,因为int的数据大小为4字节,它已升级,因此您将看到值0xFFFF 0xFFFC的其余部分

这就是使用强制转换的原因,告诉编译器将一种数据类型强制转换为另一种数据类型,这与上面Gregory Pakosz的回答相结合

希望这有帮助, 顺致敬意,
Tom.

short
是一种有符号类型。在你的实现中有16位。0xFFFC表示整型常量65532,但当转换为16位有符号值时,结果为-4

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

0xFFFFFC是-4的32位表示形式。所发生的一切就是将您的值从一种类型转换为更大的类型,以便将其用作数组索引。它保留其值,即-4

如果确实要访问阵列的65533元素,则应:

  • var
    使用较大的类型
    int
    在32位窗口上就足够了,但通常
    size\u t
    是一种无符号类型,它保证足够大,可以用于非负数组索引
  • 使用一个
    无符号的short
    ,它只为本例提供了足够的空间,但如果您想再向前走4步,则会出错

在您的问题主题中,您已经猜到这里发生了什么:是的,类型
short
的值“自动扩展”为类型
int
的值。这个过程被称为整体提升。这就是它在C语言中的工作原理:每次使用小于
int
的整数值时,该值总是隐式提升为
int
类型的值(无符号值可以提升为
unsigned int
)。值本身不会更改,当然,只会更改值的类型。在上面的示例中,pattern
0xFFFC
表示的16位
short
值与pattern
0xFFFFFC
表示的32位
int
值相同,即小数形式的
-4
。顺便说一句,这让你的问题的其余部分听起来很奇怪:不管是否升级,你的代码正在试图访问
b[-4]
。升级到
int
不会改变任何事情。

你的编译器是什么?也许你的编译器不支持
short
请给我举一个世界上不支持
short
类型的C编译器…@Pakosz cool-down@SjB short是通用C标准的保证。。。比如:现在是刀枪不入的时候,但在C语言中仍然有short=16位。长=32位,等等,等等。。。int,是机器相关的。@jpinto3912:短和长也不是保证固定大小的。您从观察中得出的结论是错误的。。。短变量为16位。执行var++循环,查看溢出的位置。@jpinto3912您的co是什么 char ch = '2'; int j = ch + 1;