这也是Ansi C中未定义的行为吗?

时间:2014-01-11 08:46:32

标签: c ansi undefined-behavior

如果代码是这样的,那么它必须是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 个答案:

答案 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。