Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.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 使用整型格式说明符而不是短int:为什么代码的行为是这样的?_C_Memory_Short_Integer Overflow_Format Specifiers - Fatal编程技术网

C 使用整型格式说明符而不是短int:为什么代码的行为是这样的?

C 使用整型格式说明符而不是短int:为什么代码的行为是这样的?,c,memory,short,integer-overflow,format-specifiers,C,Memory,Short,Integer Overflow,Format Specifiers,当我为下面的程序提供4个整数作为输入时(比如a=10,b=20,d=30,e=40),它计算c=a+b=0和f=d+e=70。 我知道这种不寻常的行为是因为我对short int使用了错误的格式说明符,但是这里到底发生了什么?为什么最后两个输入的和是正确的,而前两个数字的和总是=0 #include<stdio.h> void main() { short int a, b, c, d, e, f; scanf("%d%d%d%d", &a, &b,

当我为下面的程序提供4个整数作为输入时(比如a=10,b=20,d=30,e=40),它计算
c=a+b=0
f=d+e=70
。 我知道这种不寻常的行为是因为我对short int使用了错误的格式说明符,但是这里到底发生了什么?为什么最后两个输入的和是正确的,而前两个数字的和总是=0

#include<stdio.h>

void main()
{
    short int a, b, c, d, e, f;
    scanf("%d%d%d%d", &a, &b, &e, &d);
    c = a + b;
    f = d + e;
    printf("%d\n%d\n", c, f);
}
#包括
void main()
{
短int a、b、c、d、e、f;
scanf(“%d%d%d%d”、&a、&b、&e、&d);
c=a+b;
f=d+e;
printf(“%d\n%d\n”,c,f);
}

这是未定义的行为,因此如果不详细分析实现,就无法给出“为什么”。但最有可能的是,编译器选择的变量布局导致在读入其他变量时,其中一些变量被破坏

使用我的编译器,在添加一行打印出
a、b、d、e的地址后,我得到了输出

0
70
0x7fffa94d30ca
0x7fffa94d30c8
0x7fffa94d30c6
0x7fffa94d30c4
所以发生的事情很可能是

  • a
    的扫描在
    0x7fffa94d30ca
    的低位字节中存储了10,在接下来的三个字节中存储了0(little endian机器),覆盖了堆栈中未分配给任何变量的两个字节,不幸的是没有致命的后果
  • b
    的扫描存储在
    0x7fffa94d30c8
    处的字节中的20,将0扫描到接下来的三个字节,覆盖分配给
    a
    的两个字节,因此将
    a
    设置为0
  • e
    的扫描(巧妙地按照字母顺序和声明顺序完成)存储在
    0x7fffa94d30c4
    处的字节中30个,并将0扫描到接下来的三个字节中,最后两个字节是
    d
    分配的位置,但
    d
    随后会被扫描,因此
  • d
    的扫描在
    0x7fffa94d30c6
    的字节中存储了40,在接下来的三个字节中存储了0,用0覆盖
    b
  • 添加
    c=a+b
    的结果为0,因为扫描其他变量时两个变量都被覆盖;添加
    f=d+e
    的结果为70,因为扫描后
    d
    e
    都没有被覆盖
  • 强制将
    c
    分配到堆栈上,并通过将其地址打印到
    d
    而不是
    b
    覆盖
    c
    而不是
    b
    而不将其放在寄存器中,相应地,添加
    c=a+b
    导致20


    由于使用
    %d
    格式说明符扫描
    short int
    变量是未定义的行为,任何事情都可能发生,但如果编译器不利用UB,简单的解释将是正确的。

    %d
    是用于读取
    int
    的格式代码。如果
    short
    小于
    int
    %hd
    是读取
    short int
    的正确格式代码,发生的情况是“%d”指示scanf读取和解析输入中的数字,将其转换为int,并将该int存储在相应的地址。通常,int是32位(四个字节),短int是16位(两个字节),尽管这可能有所不同

    尽管scanf正在为每个“%d”写入四个字节,但您只为&a、&b、&e和&d中的每一个传递了两个字节。因此,其中两个字节指向正确的地址,另外两个字节指向&a、&b、&e和&d旁边的任何位置。它们中的一些相邻,并被散乱的字节覆盖


    显然,这是一个非常糟糕的代码,永远不应该使用。您无法计算哪些变量将位于内存中其他变量的旁边。

    在许多平台上,
    short
    的大小为2个字节,
    %d
    格式规范告诉
    scanf()
    目标有4个字节。因此,考虑当<代码> ScSff()/Cux>将4个字节写入一个只有2个可能副本的变量位置时会发生什么情况。