【问题标题】:Why doesn't scanf read the value correctly?为什么 scanf 不能正确读取值?
【发布时间】:2013-09-16 07:35:04
【问题描述】:

谁能告诉我这里出了什么问题?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define ERROR 0
#define MAX_INPUT_LINE 80
#define print(x) {fputs(x,stdout);}
#define SUCCESS 1

int main (long argc, char *argv[])
{
   int mode;
   printf("1 for hexidecimal or 2 for binary");
   scanf("%d", mode);

   printf("\n\n\nThe value of mode is %d\n", mode);
   return 0;
}

当我为二进制输入 2 时,我得到了这个:

The value of mode is 2665564

显然我应该得到 2,我做错了什么?它是我的编译器,是因为我使用的是 Cygwin 吗?为什么不是模式2??

【问题讨论】:

  • 你做错的是忽略你的编译器警告信息。

标签: c unix compiler-construction printf scanf


【解决方案1】:

你的 scanf 是错误的。应该是:

scanf("%d", &mode);

&amp; 告诉编译器发送scanf 一个指针 到mode(即它的地址),而不是mode 的实际值。这样scanf 可以使用新的扫描值更新mode。

【讨论】:

    【解决方案2】:

    这是 C,不是 Java。当你使用像scanf (...) 这样的函数时,因为你不能通过引用传递变量,你应该传递一个指向将保存值的变量的指针。

    改用以下内容:

    scanf ("%d", &mode);
    

    使用 (&) 将传递地址模式,而不是隐式转换模式到 (int *)。

    在这个例子中你真的很幸运,这并没有导致你的程序崩溃。如果 mode 的值为 0 并被强制转换为指针以满足此功能,那么您很可能会取消对 NULL 指针的引用。

    【讨论】:

      【解决方案3】:

      你用错了scanf。对于整数值、浮点值或字符等内容,您需要为要填充的变量提供一个指针。使用地址运算符&amp; 最容易做到这一点,例如

      scanf("%d", &mode);
      

      scanf 系列函数在读取字符串时也需要一个指针,但由于字符串已经 是 指针(或衰减为指针的数组),因此您不需要地址运算符对于字符串。

      我建议您阅读this scanf reference,因为它包含一个表格,显示了不同格式代码所期望的参数。

      【讨论】:

        【解决方案4】:

        scanf 的第二个参数是错误的,因为格式是%d,所以它需要一个指向int 的指针。

        scanf("%d", &mode);
        //          ^
        

        【讨论】:

          【解决方案5】:

          scanf 正在接受指针,然后尝试将值放入指针指向的位置,这意味着您无法发送 mode 您需要发送 &amp;mode。发送mode 将导致未定义行为。

          做

          scanf ("%d", &mode);
          

          您的完整代码:

          #include <stdlib.h>
          #include <stdio.h>
          #include <string.h>
          
          #define ERROR 0
          #define MAX_INPUT_LINE 80
          #define print(x) {fputs(x,stdout);}
          #define SUCCESS 1
          
          int main (long argc, char *argv[])
          {
             int mode;
             printf("1 for hexidecimal or 2 for binary");
             scanf("%d", &mode);
          
             printf("\n\n\nThe value of mode is %d\n", mode);
             return 0;
          }
          

          如果您想以十六进制模式打印数字,我还要说明,请使用%x:

          printf("%x", mode);
          

          【讨论】:

            【解决方案6】:

            scanf 的附加参数是地址。参考here。

            顺便说一下,附加参数应该指向已分配的对象,其类型由格式字符串中的相应格式说明符指定。

            所以只需将main() 中的第 3 行更改为:

            scanf("%d", &mode);
            

            【讨论】:

              【解决方案7】:

              scanf 原型是 int scanf(const char *format, ...);因此使用 '&' 发送地址...

              【讨论】:

              • 这实际上并不能解释为什么需要使用运算符的地址。许多函数使用不需要/期望指针的...(可变长度参数列表)。 scanf 需要指针的原因是因为它使用可变长度参数来存储解析值。
              • 感谢指正。我很着急,想告诉在代码中使用运算符的地址,但没有很好地构建我的答案。
              【解决方案8】:

              您很幸运,您的程序不会因内存错误而崩溃。由于mode 未初始化,其值未定义,因此您将整数存储在随机地址。

              稍后,您以十进制打印该地址。

              这应该“有效”(如果编译器接受):

              printf("%d\n",*mode);
              

              或

              printf("%d\n",*(int*)mode);
              

              为了澄清,我显然不建议取消引用未初始化的指针。我只是想解释为什么程序没有崩溃,并展示如何在保持虚假 scanf 不变的情况下获取输入的值(与所有其他正确解决根本原因的回复不同)。在 32 位环境中,int 和指针都存储在 4 个字节中,因此 CPU 无法区分。当然,编译器至少应该输出带有此类虚假代码的警告。

              【讨论】:

              • 我不认为取消引用未初始化的指针是一个好技巧。对任何人。而且由于它甚至不是一个指针,所以这是一个更糟糕的主意。
              • @NathanFellman 模式值不变,它用作存储整数的地址。
              【解决方案9】:

              你的代码应该是这样的:

              scanf("%d", &mode);
              

              您在代码中错过了&amp; 符号。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-11-04
                • 2015-07-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多