如果代码是这样的,那么它必须是undefined behavior。
char *String = "Stack Overflow"; //undefined behavior
因此,以下还是一个未定义的行为? 但我的大部分参考书都是这样写的!
char *Print (char *String)
{
return String;
}
int main (void)
{
printf ("%s", Print("Stack Overflow"));
return 0;
}
为避免编写未定义的行为代码,为什么不这样做呢?
char *Print (char String[16])
{
return String;
}
int main (void)
{
printf ("%s", Print("Stack Overflow"));
return 0;
}
答案 0 :(得分:6)
如果这样的代码,它必须是未定义的行为。
char *String = "Stack Overflow"; //undefined behavior
一定是吗?为什么?不,不是。也许将字符串文字分配给非{ - 1}}指针并不是最好的主意,但只要不修改其内容,就可以了。
第二个构造也未定义。字符串文字具有静态存储持续时间。如果你返回一个指向它的第一个字符的指针,它将无论指针的生命周期和范围如何都是有效的(只要它被正确复制,例如它被传递给函数或从函数返回,这正是在你的代码)。
答案 1 :(得分:3)
定义这样的字符串不是未定义的行为。你写的时候会发生什么,
char *String = "Stack Overflow";
如果编译器将在可执行文件的数据段中保留一个字节数组,并将“Stack Overflow”字符串放在那里。然后它会将String
指针指向它。只有当您尝试访问此指针时,行为才会被定义。
请注意,总体而言,最好避免额外的间接,只需定义:
static const char String[] = "Stack Overflow";
区别很微妙,但是你保存了一个指针,你还告诉编译器String是不可变的,它可能会放在一个只读的内存页面。
答案 2 :(得分:1)
在您最近的编辑之后,似乎您担心字符串文字中的所有字符 - 即字符数组 - 被推入堆栈以进行函数调用。这是不正确的。只传递一个指向数组的指针,指向字符串文字的指针 - 或任何字符串 - 总是大小相同,编译时在编译时就知道了。
至于你的第一个例子,它没有任何未定义的行为。字符串文字 - 引号之间的文本 - 由编译器写入字符数组。然后将指针(即数组的“地址”)分配给正确声明为char *
的变量 - 尽管const char *
或const char * const
可能更合适,具体取决于实现细节和程序员意图。
答案 3 :(得分:0)
尝试修改 String
变量的内容未定义。
使用char*
,将其作为参数传递并从函数返回它不是UB。