【问题标题】:wrong output from a simple C code block简单 C 代码块的错误输出
【发布时间】:2013-06-18 17:03:33
【问题描述】:

我预计输出是“Sunday Monday”,但实际输出是“Monday Monday”,这是为什么呢?

#include <stdio.h>
#include <string.h>
static const char *msg[] = {"Sunday", "Monday", 
"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
char *get_a_day(int idx)
{
    static char buf[20];
    strcpy(buf, msg[idx]);
    return buf;
}

int main(void)
{
    printf("%s %s\n", get_a_day(0), get_a_day(1));
    return 0;
}

【问题讨论】:

  • 当您使用单独的printf 调用时会发生什么?
  • 对不起,我上次编辑时忘记写'return'了......我的错

标签: c pointers static


【解决方案1】:

您将buf[] 声明为static,这意味着所有实例将共享一个内存位置。

get_a_day() 似乎隐式返回buf[],因此对get_a_day() 的两个调用都返回指向同一缓冲区的指针。

第一次调用将buf[] 设置为"Sunday",并返回指向buf 内存位置的指针。然后第二次调用将buf[] 设置为"Monday",覆盖"Sunday",并返回指向buf 内存位置的指针——与第一次调用相同的内存位置。然后指向buf 的指针作为第二个和第三个参数传递给printf。由于buf 包含"Monday"(之前已覆盖"Sunday"),printf() 打印Monday Monday。

为什么buf 需要是静态的?如果您删除此关键字并正确分配内存,事情应该会如您所愿。另外,你需要buf 吗?如果你刚刚返回msg[i],你会得到你期望的结果。

另一件事:您不应该隐式返回这样的值。可维护性大幅下降,代码的意图不明确。你应该明确地return你想要返回的值。

【讨论】:

    【解决方案2】:

    如果你想要一个解释,其他答案解释得很好。

    如果你只是想让你的程序工作,这应该可以解决它:

    const char *get_a_day(int idx)
    {
        return msg[idx];
    }
    

    【讨论】:

      【解决方案3】:

      这是因为您使用的是 strcpy。 strcpy 替换缓冲区中的整个字符串。因此,第二次调用会覆盖第一次调用(在某些平台上,第一次调用将覆盖第二次调用,因为它们的评估顺序相反)。更不用说没有回报了。试试这个代码:

      char* get_a_day( int idx, char* buf )
      {
          strcpy(buf, msg[idx]);
          return buf;
      }
      
      int main(void)
      {
          char buf0[20];
          char buf1[20];
      
          printf("%s %s\n", get_a_day(0, buf0), get_a_day(1, buf1));
          return 0;
      }
      

      【讨论】:

        【解决方案4】:

        您应该启用所有警告(例如使用gcc -Wall -g 编译)并学习使用调试器(例如gdb)。

        请注意,您的 get_a_day 函数被声明为返回 char* 但不返回任何内容(并且您的编译器会警告您)。所以你有一个undefined behavior,一切都可能发生(并且仍然符合 C 规范)。

        即使您在 get_a_day 函数的末尾添加 return buf;,它也会返回 same 指针,因为 buf 是 static(如果在 @987654330 中调用两次@像你一样)。

        您或许应该考虑返回一个堆分配的字符串,并约定 调用者 应该释放它。但在您的特定情况下,返回 msg[idx] 就足够了。

        【讨论】:

        • 是的,应该分配一个新的缓冲区并在最后删除它。加上整个不归路。
        • 它不返回任何东西,它填充了一个本地缓冲区buf,然后它立即消失了。他显然打算返回buf,但这也行不通(实际上,尽管错了,它也可能行得通)。
        • @LeeDanielCrocker:注意buf 被声明为static,因此代码没有返回本地缓冲区。
        • 啊,原来如此。不知何故没注意到。因为只有一个缓冲区,所以在 printf() 中调用它两次仍然会有问题。
        猜你喜欢
        • 2014-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-19
        相关资源
        最近更新 更多