替换(不修改)'const' 值,合法吗?

Replacing (not modifying) 'const' values, legal?

遵守以下代码:

const char *str1 = "foo";
printf("1.1: %s\n", str1);
str1 = "bar";
printf("1.2: %s\n\n", str1);

const char *str2[] = { "foo", "bar" };
printf("2.1: %s\n", str2[0]);
str2[0] = "baz";
printf("2.2: %s\n\n", str2[0]);

char *str3 = malloc(4);
strcpy(str3, "foo"); 
const char *str4[] = { str3, "bar" };
printf("3.1: %s -- %s\n", str4[0], str4[1]);
//str4[0][0] = 'z';
str4[0] = "bar";
str4[1] = "baz";
printf("3.2: %s -- %s\n", str4[0], str4[1]);
free(str3);

将其包装在标准 main 函数中并使用 gcc -Wall -Wextra -o test test.c 进行编译,这不会给出任何警告,输出为:

1.1: foo
1.2: bar

2.1: foo
2.2: baz

3.1: foo -- bar
3.2: bar -- baz

取消注释唯一的注释行时,gcc 会报错 error: assignment of read-only location ‘*str4[0]’。当然这是预料之中的,我只是为了完整性添加了那一点。

根据我的理解,所有其他分配都是有效的,因为我没有修改已经存在的只读内存,我将其全部替换为 另一个 内存块(然后也标记为只读)。但这在所有 C 编译器中都是合法的,还是它仍然依赖于实现,因此会导致未定义的行为?很难找到这方面的好信息,因为它似乎总是关于通过指针魔术修改 现有 内存或将 const 丢弃。

在此声明中

const char *str1 = "foo";

指针(变量)str1 不是常量。指针 str1 指向的字符串文字是常量。即(非常量)指针 str1 指向 const char.

类型的常量对象

所以你不能改变指针指向的文字,例如

str1[0] = 'g';

但是您可以更改变量 str1 本身,因为它不是常量

str1 = "bar";

要将指针 str1 声明为常量指针,您应该编写

const char * const str1 = "foo";

这种情况下可以不写

str1 = "bar";

因为现在指针str1本身是常量。

注意尽管在 C 中字符串文字具有非常量字符数组类型,但是您不能更改字符串文字。任何更改字符串文字的尝试都会导致未定义的行为。

那是你可能不会写

char *str1 = "foo";
str1[0] = 'g';