我有以下代码:
char* p;
void func1()
{
p = "hello world";
}
int main()
{
func1();
printf(p);
return 0;
}
这段代码在这里运行良好,但我想知道它是否正确或是否存在“未定义的行为”。
“hello world”会在func1()外部仍然存在吗?
我有以下代码:
char* p;
void func1()
{
p = "hello world";
}
int main()
{
func1();
printf(p);
return 0;
}
这段代码在这里运行良好,但我想知道它是否正确或是否存在“未定义的行为”。
“hello world”会在func1()外部仍然存在吗?
字符串字面值是具有静态存储期的字符数组(参见C11 6.4.5/6),因此它们的生命周期延伸到整个程序的结束。您的代码很好。
答案是“是的”——“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$
(*注意:据我所知,它可能是实现定义,但也有可能不是)
p
应该是char const *
。由于向字符串字面量写入数据会导致未定义行为,这样做将有助于编译器诊断错误。 - M.M