c - 我编码不正确吗?

标签 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。

最佳答案

你的问题出在这里:

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 因为 age1 但它会被 scanf 覆盖code> 下次你得到输入时。

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

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

关于c - 我编码不正确吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12559164/

相关文章:

c++ - _mm_comieq_ss Clang 和 GCC 之间的区别

java - JVM TI 的链接库名称

c - ANSI C(ISO C90): Can scanf read/accept an unsigned char?

c - 在C中打印二维字符数组

c - 伸展树(Splay Tree)中自下而上和自上而下的方法有什么区别?

c - 数组是常量数据类型吗

c++ - 以字符数组为参数的模板元编程

c - linux服务器上的编译错误(C项目)

c - 针对 glib 进行编译时出现链接器错误...?

c - 在不强制转换的情况下对 unsigned char * 使用字符串方法