替换(不修改)'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';
遵守以下代码:
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';