2

几十年前我做过一些 C 编程。我正在尝试重新学习语言。我写了这个。我得到了一些意想不到的东西。当我将“short int”更改为“int”时,它似乎有效。任何人都可以查看我的代码以查看它是否有任何问题或者这是编译器问题。我在 Linux 上使用 gcc。

#include <stdio.h>

int main(void) {

    short int age = 0;
    short int num_1_yr_olds = 0;
    short int num_2_and_3_yr_olds = 0;
    short int num_above_3_yr_olds = 0;

    while(1) {

        printf ("Enter age: ");
        scanf ("%d", &age);

        if (age < 1) {
            break;
        }

        switch (age) {
            case 1:
                ++num_1_yr_olds;
                break;
            case 2:
            case 3:
                ++num_2_and_3_yr_olds;
                break;
            default:
                ++num_above_3_yr_olds;
                break;
        }
    }
    printf ("Number of 1 year olds = %d\n", num_1_yr_olds);
    printf ("Number of 2 and 3  year olds = %d\n", num_2_and_3_yr_olds);
    printf ("Number above 3 year olds = %d\n", num_above_3_yr_olds);
}

输入

Enter age: 1
Enter age: 1
Enter age: 1
Enter age: -1

输出

Number of 1 year olds = -1
Number of 2 and 3  year olds = 0
Number above 3 year olds = 0

num_1_yr_olds 值被搞砸了。我期望一个 3,我得到一个 -1。无论输入如何,num_1_yr_olds 的值都会变为 -1。

4

2 回答 2

9

你的问题出在这里:

short int age = 0;
:
scanf ("%d", &age);

您确实需要确保您的数据类型与您的格式字符串匹配。a 的正确格式说明符short int%hd,不是%d

一些编译器实际上会检查这个并警告你。

可能发生的是数据和格式字符串的未对齐导致short int成为“错误”值,因此计数被搞砸了。


更深入地说,对于像 x86 这样的二进制补码、小端架构,将 an 扫描int到 ashort可能会将最低有效的一半放入age,将最高有效的一半放入num_1_year_olds(如果它与内存相邻age)。

从图形上看,这样想可能更清楚:

                         shorts in memory
                     +-----------------------+
What scanf("%hd") =< |          age          | \
  will write to.     +-----------------------+  = What scanf("%d")
                     |    num_1_year_olds    | /    will write to.
                     +-----------------------+
                     | num_2_and_3_year_olds |
                     +-----------------------+
                     | num_above_3_year_olds |
                     +-----------------------+

所以,当你进入时1age成为1num_1_year_olds成为0

每次您这样做时,它都会增加,num_1_year_olds因为age它会在您下次获得输入时1被覆盖。scanf

当您最终输入-1(二进制补码中的所有 1 位)时,age变为.-1num_1_year_olds

然后,因为age小于一,循环中断,值就是你所看到的:{-1, 0, 0}.

于 2012-09-24T05:15:29.877 回答
2

尝试

scanf ("%hd", &age);

由于年龄是短整数类型。

于 2012-09-24T05:15:44.433 回答