全局字符指针指向函数内定义的常量字符串

3

我有以下代码:

char* p;


void func1()
{
    p = "hello world";
}

int main()
{
    func1();

    printf(p);

    return 0;
}

这段代码在这里运行良好,但我想知道它是否正确或是否存在“未定义的行为”。

“hello world”会在func1()外部仍然存在吗?


2
这是有效的,但是 p 应该是 char const *。由于向字符串字面量写入数据会导致未定义行为,这样做将有助于编译器诊断错误。 - M.M
2个回答

4

字符串字面值是具有静态存储期的字符数组(参见C11 6.4.5/6),因此它们的生命周期延伸到整个程序的结束。您的代码很好。


3

答案是“是的”——“hello world”仍将存在于func1()之外。

这是因为字符串文字实际上并没有存储在func1的堆栈中,而是(通常)存储在全局表中。

然而,有两点需要注意:

1)即使是常量字符串,也不应该使用printf(str)这样的写法——如果字符串恰好包含“%”字符,则它将被解释为格式的一部分,printf最终会读取超出边界的内容,导致未定义的行为。例如:

char* str = "100% string!";
...
printf(str);

重要的部分是% s -- printf将把它解释为格式字符串的一部分,并期望在其参数中提供另一个字符串;由于您没有提供,它最终将尝试取消引用任意内存,并且您将获得未定义的行为。

相反,您可以这样调用printf:

printf("%s", str);

这是安全的,因为只有第一个参数被解释为格式字符串。

2) 但是你在其他地方确实存在微妙的未定义行为(*请参见下文)--也就是说,C标准要求你的输出以换行符(\n)结尾--它不必在与主字符串相同的printf调用中,但最终必须出现。

所以这些都没问题:

printf("hello, world");
printf("\n"); // can also just be "hello world\n"
//<program exit>

但这不是:
printf("hello, world");
//<program exit>

实际上,实现时并不会出现问题,但是当程序不输出最后的换行符时,这会给用户带来麻烦,因为在程序完成后终端会打印自己的一些内容(这里 user$ 是 shell 提示符):
user$ ./hello-nl
hello, world
user$

与没有换行符:

user$ ./hello-nl
hello, worlduser$

(*注意:据我所知,它可能是实现定义,但也有可能不是)


1
它是实现定义的,而不是未定义行为。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接