如果代码是这样的,它必须是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;
}
4条答案
按热度按时间vi4fp9gy1#
如果代码是这样的,它一定是一个未定义的行为。
**必须是?为什么?**不,不是。也许将字符串文字分配给指向非
const
的指针不是最好的主意,但只要不修改其内容,就可以。第二个结构也不是未定义的。字符串文字有静态存储期限。如果你返回一个指向第一个字符的指针给它,它将是有效的,不管指针的生命周期和作用域如何(只要它被正确地复制,例如,它被传递给函数或从函数返回,这正是在你的代码中发生的事情)。
bzzcjhmw2#
像这样定义一个字符串并不是一个未定义的行为。
如果是这样,编译器将在可执行文件的数据段中保留一个字节数组,并将“Stack Overflow”字符串放在那里。然后它将把
String
指针指向它。只有当你试图访问这个指针时,行为才会被定义。请注意,总的来说,最好避免额外的间接,并简单地定义:
区别很细微,但是你保存了一个指针,同时你也告诉编译器String是不可变的,它可能会被放在一个只读内存页中。
yacmzcpb3#
在你最近的编辑之后,你似乎担心一个字符串中的所有字符--也就是一个字符数组--都被推送到堆栈上进行函数调用。这是不正确的。只有一个指向数组的指针被传递,而指向字符串的指针--或者任何字符串--总是相同的大小,并且在编译时被编译器知道。
至于你的第一个例子它没有任何未定义的行为。字符串字面量-引号之间的文本-由编译器写入字符数组。然后指针-即数组的“地址”-被分配给正确声明为
char *
的变量-尽管X1 M1 N1 X或X1 M2 N1 X可能更合适,这取决于实现细节和程序员意图。qmb5sa224#
尝试修改
String
变量的内容是未定义的。使用
char*
,将其作为参数传递并从函数返回它不是UB。