我错误地编码了吗?

时间:2012-09-24 05:13:14

标签: c gcc

几十年前,我做了一些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。

2 个答案:

答案 0 :(得分:9)

你的问题在于:

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

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

有些编译器会检查这个并警告你。

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


更深入地说,对于像x86这样的小端结构,将int扫描到short可能会将最不重要的一半放入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 |
                     +-----------------------+

因此,当您输入1时,age变为1num_1_year_olds变为0

每次执行此操作时,num_1_year_olds都会增加age,因为1scanf,但下次您输入时会被-1覆盖。

当您最终输入age(所有1位为二进制补码)时,-1变为num_1_year_oldsage也是如此。

然后,由于{-1, 0, 0}小于1,因此循环中断,并且您看到的值为{{1}}。

答案 1 :(得分:2)

尝试

scanf ("%hd", &age);

因为age是short int类型。