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

lo8azlld  于 2023-03-29  发布在  其他
关注(0)|答案(4)|浏览(98)

如果代码是这样的,它必须是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;
}
vi4fp9gy

vi4fp9gy1#

如果代码是这样的,它一定是一个未定义的行为。

char *String = "Stack Overflow"; //undefined behavior

**必须是?为什么?**不,不是。也许将字符串文字分配给指向非const的指针不是最好的主意,但只要不修改其内容,就可以。

第二个结构也不是未定义的。字符串文字有静态存储期限。如果你返回一个指向第一个字符的指针给它,它将是有效的,不管指针的生命周期和作用域如何(只要它被正确地复制,例如,它被传递给函数或从函数返回,这正是在你的代码中发生的事情)。

bzzcjhmw

bzzcjhmw2#

像这样定义一个字符串并不是一个未定义的行为。

char *String = "Stack Overflow";

如果是这样,编译器将在可执行文件的数据段中保留一个字节数组,并将“Stack Overflow”字符串放在那里。然后它将把String指针指向它。只有当你试图访问这个指针时,行为才会被定义。
请注意,总的来说,最好避免额外的间接,并简单地定义:

static const char String[] = "Stack Overflow";

区别很细微,但是你保存了一个指针,同时你也告诉编译器String是不可变的,它可能会被放在一个只读内存页中。

yacmzcpb

yacmzcpb3#

在你最近的编辑之后,你似乎担心一个字符串中的所有字符--也就是一个字符数组--都被推送到堆栈上进行函数调用。这是不正确的。只有一个指向数组的指针被传递,而指向字符串的指针--或者任何字符串--总是相同的大小,并且在编译时被编译器知道。
至于你的第一个例子它没有任何未定义的行为。字符串字面量-引号之间的文本-由编译器写入字符数组。然后指针-即数组的“地址”-被分配给正确声明为char *的变量-尽管X1 M1 N1 X或X1 M2 N1 X可能更合适,这取决于实现细节和程序员意图。

qmb5sa22

qmb5sa224#

尝试修改String变量的内容是未定义的。
使用char*,将其作为参数传递并从函数返回它不是UB。

相关问题