【问题标题】:have I coded this incorrectly?我编码不正确吗?
【发布时间】:2012-09-24 05:13:13
【问题描述】:

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

【问题讨论】:

    标签: c gcc


    【解决方案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 变为 1 并且 num_1_year_olds 变为 0

    每次您这样做时,它都会增加num_1_year_olds,因为age1,但下次您输入时,scanf 会覆盖它。

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

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

    【讨论】:

    • 这确实有效。我确实意识到这是内存问题,但不确定是什么原因造成的。 %hd 是否一直是 C 的一部分?
    • @rpat:好吧,至少回到 c89。它甚至在我的第二版 K&R(ANSI 版)中。在此之前,我在 很久 之前就把那些书扔掉了。
    • 感谢分享您的智慧。我有一个可以追溯到 88 年的 K&R。我想需要摆脱它。你能推荐一本书吗?
    • @rpat,我使用的书是 ISO 标准,但那是因为我知道更简单的东西,它只是我要查找的语言的黑暗角落,我找到了这些东西的标准更好。我不会向初学者推荐它,除非他们是一个严肃的受虐狂:-)
    • 话虽如此,我家里有一本早期版本的 ABC,我记得它很有用。如果您想查看,请参阅amazon.com/Book-Programming-4th-Edition/dp/0201183994
    【解决方案2】:

    试试

    scanf ("%hd", &age);
    

    因为年龄是短整数类型。

    【讨论】:

      猜你喜欢
      • 2018-12-23
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      • 2018-08-22
      • 2015-02-08
      • 2012-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多