来自简单C代码块的错误输出

时间:2013-06-18 17:03:34

标签: c pointers static

我预计输出是“星期一星期一”,但实际输出是“星期一”,为什么会这样?

#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;
}

4 个答案:

答案 0 :(得分:3)

如果您想要解释,其他答案可以解释清楚。

如果您只是想让您的程序正常工作,那么应该解决它:

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

答案 1 :(得分:3)

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

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

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

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

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

答案 2 :(得分:2)

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

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

即使您在return buf;函数末尾添加get_a_day,它也会返回相同的指针,因为bufstatic (如果像printf那样在msg[idx]中调用两次)。

您应该考虑返回堆分配的字符串,并且具有调用者应该释放它的约定。但在您的特定情况下,返回{{1}}就足够了。

答案 3 :(得分:2)

因为你正在使用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;
}