1

我希望输出是“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;
}
4

4 回答 4

3

如果您需要解释,其他答案可以很好地解释。

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

const char *get_a_day(int idx)
{
    return msg[idx];
}
于 2013-06-18T17:10:27.903 回答
3

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

get_a_day()似乎隐含地 return buf[],所以两个调用都get_a_day()返回指向同一个缓冲区的指针。

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

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

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

于 2013-06-18T17:12:56.063 回答
2

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

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

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

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

于 2013-06-18T17:06:05.927 回答
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;
}
于 2013-06-18T17:08:17.677 回答