如果 char*s 是只读的,为什么我可以覆盖它们?
If char*s are read only, why can I overwrite them?
我的课程告诉我,char*s 只是 static/read,所以我认为这意味着您不能在定义它们之后对其进行编辑。但是当我 运行:
char* fruit = "banana";
printf("fruit is %s\n", fruit);
fruit = "apple";
printf("fruit is %s\n", fruit);
然后它编译正常并给我:
fruit is banana
fruit is apple
为什么?我是否误解了只读的含义?很抱歉,如果这很明显,但我是编码新手,我无法在线找到答案。
提供的代码片段不会更改字符串文字本身。它仅更改存储在指针 fruit
.
中的值
你可以想象这些线条
char* fruit = "banana";
fruit = "apple";
以下方式
char unnamed_static_array_banana[] = { 'b', 'a', 'n', 'a', 'n', 'a', '[=11=]' };
char *fruit = &unnamed_static_array_banana[0];
char unnamed_static_array_apple[] = { 'a', 'p', 'p', 'l', 'e', '[=11=]' };
fruit = &unnamed_static_array_apple[0];
这些语句不会更改对应于字符串文字的数组。
另一方面,如果你会尝试写
char* fruit = "banana";
printf("fruit is %s\n", fruit);
fruit[0] = 'h';
^^^^^^^^^^^^^^
printf("fruit is %s\n", fruit);
也就是说,如果您尝试使用指向字符串文字(指向字符串文字的第一个字符)的指针更改字符串文字,则程序将具有未定义的行为。
来自 C 标准(6.4.5 字符串文字)
7 It is unspecified whether these arrays are distinct provided their
elements have the appropriate values. If the program attempts to
modify such an array, the behavior is undefined.
你的课程教给你的是正确的!
当您首先定义 char* fruit = "banana"
时,您基本上将 fruit
作为指向 常量字符 的指针。字符串的 7 个字节(包括空终止符)位于目标文件的 .ro
部分(部分名称显然会因平台而异)。
当您将 char 指针 fruit 重置为 "apple" 时,它只是指向只读部分中包含 "apple"
的另一个内存位置
本质上,当你说 fruit 是一个 常量 时,它指的是 fruit
是指向 const
内存的指针。如果您将其定义为 const pointer to a const string
:-
char* const fruit = "banana";
编译器会阻止您将其重置为 "apple"
基本上,当你执行
char* fruit = "banana";
您设置了一个指针 fruit
指向 "banana" 的第一个字母。打印出来时,C 基本上从 'b' 开始并一直打印字母,直到它在末尾遇到一个 [=13=]
空字符。
到时候说
fruit = "apple";
您已将指针 fruit
更改为现在指向 "apple"
的第一个字母
首先,char*
不是只读的。 char * const
是。而且它们不同于char const *
。文字字符串(例如 "banana")应该是,但不一定是。
char * const cpfruit = "banana";
cpfruit = "apple"; // error
char const * cpfruit = "banana";
cpfruit[0] = 'x'; // error
char * ncfruit = "banana";
ncfruit[0] = 'x'; // compile will allow, but may cause run-time error.
您正在将变量 fruit
指向不同的字符串。您只是在覆盖地址(位置)。编译器将看到您的常量字符串 "banana" 和 "apple" 并将它们分别存储在程序内存中。假设字符串 "banana" 进入位于地址 1
的内存单元,并且 "apple" 存储到内存地址 2
。现在当你这样做时:
fruit = "banana";
编译器只会将 1
分配给变量 fruit
,这意味着它指向包含字符串 banana
的地址 1
。当你这样做时:
fruit = "apple";
编译器将分配2
变量fruit
,这意味着它指向存储字符串apple
的地址2
。
在你的程序中,表达式"banana"
表示程序图像中的一个字符串文字对象,一个字符数组。表达式的值是 char *
或 "pointer to character" 类型。指针指向该数组的第一个字节,字符 'b'
.
你的 char *fruit
变量也有类型 "pointer to character" 并从这个表达式中获取它的初始值:它被初始化为指向数据的指针的副本,而不是数据本身;它仅仅指向 b
.
当您将 "apple"
分配给 fruit
时,您只是将其指针值替换为另一个指针值,因此它现在指向不同的文字数组。
要修改数据本身,您需要一个表达式,例如:
char *fruit = "banana";
fruit[0] = 'z'; /* try to turn "banana" into "zanana" */
根据 ISO C 标准,未定义此行为。 可能 "banana"
数组是只读的,但这不是必需的。
C 实现可以使字符串文字可写,或使其成为一个选项。
(如果您能够修改字符串文字,那并不意味着一切都很好。首先,根据 ISO C,您的程序仍然没有很好地定义:它不可移植。其次,C 编译器允许将具有共同内容的文字合并到同一存储中。这意味着 "banana"
在程序中的两次出现实际上可能是完全相同的数组。此外,字符串文字 "nana"
出现在某处该程序可能是出现在其他地方的数组 "banana"
的后缀;换句话说,共享相同的存储空间。修改文字可能会产生令人惊讶的效果;修改可以出现在其他文字中。)
另外 "static" 和 "read-only" 不是同义词。 C 中的大多数静态存储实际上是可修改的。我们可以创建一个可修改的静态字符数组,其中包含这样一个字符串:
/* at file scope, i.e. outside of any function */
char fruit[] = "banana";
或:
{
/* in a function */
static fruit[] = "banana";
如果我们省略数组大小,它会根据初始化字符串文字自动调整大小,并包括 space 作为空终止字节。在函数中,我们需要static
将数组放入静态存储,否则我们得到一个局部变量。
这些数组可以修改; fruit[0] = 'z'
是定义明确的行为。
此外,在这些情况下,"banana"
不表示字符数组。数组就是变量fruit
; "banana"
表达式只是指示数组初始值的一段语法:
char *fruit = "banana"; // "banana" is an object in program image
// initial value is a pointer to that object
char fruit_array[] = "apple"; // "apple" is syntax giving initial value
fruit
对象是可写的 - 它可以设置为指向不同的字符串文字。
字符串文字 "banana"
和 "apple"
不可写。您可以修改 fruit
以指向字符串文字,但如果您这样做,则不应尝试修改 fruit
指向 的内容:
char *fruit = "banana"; // fruit points to first character of string literal
fruit = "apple"; // okay, fruit points to first character of different string literal
*fruit = 'A'; // not okay, attempting to modify contents of string literal
fruit[1] = 'P'; // not okay, attempting to modify contents of string literal
尝试修改字符串文字的内容会导致未定义的行为 - 您的代码可能会按预期运行,或者您可能会遇到运行时错误,或者可能会发生完全意外的事情。为了安全起见,如果您要定义一个指向字符串文字的变量,您应该声明它 const
:
const char *fruit = "banana"; // can also be written char const *
您仍然可以分配 fruit
以指向不同的字符串:
fruit = "apple";
但是如果你试图修改 fruit
指向的内容,编译器就会对你大喊大叫。
如果你想定义一个只能指向一个特定字符串文字的指针,那么你也可以const
限定指针:
const char * const fruit = "banana"; // can also be written char const * const
这样,如果您尝试写入 fruit
指向的内容,或尝试将 fruit
设置为指向不同的对象,编译器将对您大喊大叫。
当您使用 char *p="banana";
时,字符串 banana 存储在只读内存位置。随后,当您输入 p="apple";
时,字符串 apple 存储在其他内存位置,指针现在指向新的内存位置。
您可以在每次分配后打印 p
来确认这一点。
#include<stdio.h>
int main(void)
{
char *p = "Banana";
printf("p contains address of string constant 'Banana' at 0x%p\n", p);
p="Apple";
printf("p contains address of string constant 'Apple' at 0x%p\n", p);
}
定义 C 字符串时,又名 char
数组,用双引号 "..."
,格式如下:
char * <varName> = "<someString>"
只有数组的元素是不可变的(它们的内容不能改变)。换句话说,<varName>
具有 const char *
类型(指向只读存储器的可变指针)。每次用双引号 <varName> = "<otherString>"
调用赋值运算符时,它都会自动更改指针值。下面的例子应该给出不同可能性的完整概述:
#include <stdio.h>
int main()
{
char * var_1 = "Lorem";
printf("1. %s , %p\n", var_1, var_1); // --> 1. Lorem , 0x400640
var_1 = "ipsu";
printf("2. %s , %p\n", var_1, var_1); // --> 2. ipsu , 0x400652
// var_1[0] = 'x'; // --> Segmentation fault
var_1++;
printf("3. %s , %p\n", var_1, var_1); // --> 3. psu , 0x400653
char var_2[] = {'L', 'o', 'r', 'e', 'm', '[=11=]'};
printf("4. %s , %p\n", var_2, var_2); // --> 4. Lorem , 0x7ffed0fc5381
var_2[0] = 'x';
printf("5. %s , %p\n", var_2, var_2); // --> 5. xorem , 0x7ffed0fc5381
// var_2++; //error: lvalue required as increment operand
char var_3[] = "Lorem";
printf("6. %s , %p\n", var_3, var_3); // --> 6. Lorem , 0x7ffe36a42d5c
// var_3 = "ipsu"; // --> error: assignment to expression with array type
var_3[0] = 'x';
printf("7. %s , %p\n", var_3, var_3); // --> 7. xorem , 0x7ffe36a42d5c
char * const var_4 = "Lorem";
// var_4 = "ipsu"; // --> error: assignment of read-only variable
// var_4[0] = 'x'; // --> Segmentation fault
char const * var_5 = "Lorem";
printf("8. %s , %p\n", var_5, var_5); // --> Lorem , 0x400720
var_5 = "ipsu";
printf("9. %s , %p\n", var_5, var_5); // --> ipsu , 0x400732
// var_5[0] = 'x'; // --> error: assignment of read-only location
const char * var_6 = "Lorem";
printf("10. %s , %p\n", var_6, var_6); // --> 10. Lorem , 0x400760
var_6 = "ipsu";
printf("11. %s , %p\n", var_6, var_6); // --> 11. ipsu , 0x400772
// var_6[0] = 'x'; // --> error: assignment of read-only location
const char const * var_7 = "Lorem"; // clang only --> warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
printf("12. %s , %p\n", var_7, var_7); // --> 12. Lorem , 0x400760
var_7 = "ipsu";
printf("13. %s , %p\n", var_7, var_7); // --> 13. ipsu , 0x400772
// var_7[0] = 'x'; // --> error: assignment of read-only location
char const const * var_8 = "Lorem"; // clang only --> warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
printf("14. %s , %p\n", var_8, var_8); // --> 14. Lorem , 0x400790
var_8 = "ipsu";
printf("15. %s , %p\n", var_8, var_8); // --> 15. ipsu , 0x4007a2
// var_8[0] = 'x'; // --> error: assignment of read-only location
char const * const var_9 = "Lorem";
// var_9 = "ipsu"; // --> error: assignment of read-only variable
// var_9[0] = 'x'; // --> error: assignment of read-only location
const char var_10[] = {'L', 'o', 'r', 'e', 'm', '[=11=]'};
// var_10[0] = 'x'; // --> error: assignment of read-only location
// var_10++; // --> error: lvalue required as increment operand
char const var_11[] = {'L', 'o', 'r', 'e', 'm', '[=11=]'};
// var_11[0] = 'x'; // --> error: assignment of read-only location
// var_11++; // --> error: lvalue required as increment operand
const char var_12[] = "Lorem";
// var_12[0] = 'x'; // --> error: assignment of read-only location
// var_12++; // --> error: lvalue required as increment operand
char const var_13[] = "Lorem";
// var_13[0] = 'x'; // --> error: assignment of read-only location
// var_13++; // --> error: lvalue required as increment operand
return 0;
}
此代码已在 GCC、Clang 和 Visual Studio 上测试。
基本上有3种可能:
不可变指针,可变内容
char <varName>[] = {'L', 'o', 'r', 'e', 'm', '[=17=]'};
char <varName>[] = "Lorem";
指针可变,内容不可变
char * <varName> = "Lorem";
char const * <varName> = "Lorem";
const char * <varName> = "Lorem";
const char const * <varName> = "Lorem";
char const const * <varName> = "Lorem";
不可变指针,不可变内容
char * const <varName> = "Lorem";
char const * const <varName> = "Lorem";
const char * const <varName> = "Lorem";
const char <varName>[] = {'L', 'o', 'r', 'e', 'm', '[=27=]'};
char const <varName>[] = {'L', 'o', 'r', 'e', 'm', '[=28=]'};
const char <varName>[] = "Lorem";
char const <varName>[] = "Lorem";
结论:
<typing> <varName>[] = <string>
总是 returns 不可变指针,内容的可变性独立于 <array>
格式("Lorem"
或 {'L', 'o', 'r', 'e', 'm', '[=34=]'}
)
<typing> * <varName> = "someString"
始终returns不可变内容
<typing> * const <varName> = "someString"
总是returns不可变内容和指针
char const <other>
、char const <other>
、const char const <other>
和 char const const <other>
始终创建不可变内容。
我试图详细总结 C 的数组行为 here。
我的课程告诉我,char*s 只是 static/read,所以我认为这意味着您不能在定义它们之后对其进行编辑。但是当我 运行:
char* fruit = "banana";
printf("fruit is %s\n", fruit);
fruit = "apple";
printf("fruit is %s\n", fruit);
然后它编译正常并给我:
fruit is banana
fruit is apple
为什么?我是否误解了只读的含义?很抱歉,如果这很明显,但我是编码新手,我无法在线找到答案。
提供的代码片段不会更改字符串文字本身。它仅更改存储在指针 fruit
.
你可以想象这些线条
char* fruit = "banana";
fruit = "apple";
以下方式
char unnamed_static_array_banana[] = { 'b', 'a', 'n', 'a', 'n', 'a', '[=11=]' };
char *fruit = &unnamed_static_array_banana[0];
char unnamed_static_array_apple[] = { 'a', 'p', 'p', 'l', 'e', '[=11=]' };
fruit = &unnamed_static_array_apple[0];
这些语句不会更改对应于字符串文字的数组。
另一方面,如果你会尝试写
char* fruit = "banana";
printf("fruit is %s\n", fruit);
fruit[0] = 'h';
^^^^^^^^^^^^^^
printf("fruit is %s\n", fruit);
也就是说,如果您尝试使用指向字符串文字(指向字符串文字的第一个字符)的指针更改字符串文字,则程序将具有未定义的行为。
来自 C 标准(6.4.5 字符串文字)
7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
你的课程教给你的是正确的!
当您首先定义 char* fruit = "banana"
时,您基本上将 fruit
作为指向 常量字符 的指针。字符串的 7 个字节(包括空终止符)位于目标文件的 .ro
部分(部分名称显然会因平台而异)。
当您将 char 指针 fruit 重置为 "apple" 时,它只是指向只读部分中包含 "apple"
的另一个内存位置本质上,当你说 fruit 是一个 常量 时,它指的是 fruit
是指向 const
内存的指针。如果您将其定义为 const pointer to a const string
:-
char* const fruit = "banana";
编译器会阻止您将其重置为 "apple"
基本上,当你执行
char* fruit = "banana";
您设置了一个指针 fruit
指向 "banana" 的第一个字母。打印出来时,C 基本上从 'b' 开始并一直打印字母,直到它在末尾遇到一个 [=13=]
空字符。
到时候说
fruit = "apple";
您已将指针 fruit
更改为现在指向 "apple"
首先,char*
不是只读的。 char * const
是。而且它们不同于char const *
。文字字符串(例如 "banana")应该是,但不一定是。
char * const cpfruit = "banana";
cpfruit = "apple"; // error
char const * cpfruit = "banana";
cpfruit[0] = 'x'; // error
char * ncfruit = "banana";
ncfruit[0] = 'x'; // compile will allow, but may cause run-time error.
您正在将变量 fruit
指向不同的字符串。您只是在覆盖地址(位置)。编译器将看到您的常量字符串 "banana" 和 "apple" 并将它们分别存储在程序内存中。假设字符串 "banana" 进入位于地址 1
的内存单元,并且 "apple" 存储到内存地址 2
。现在当你这样做时:
fruit = "banana";
编译器只会将 1
分配给变量 fruit
,这意味着它指向包含字符串 banana
的地址 1
。当你这样做时:
fruit = "apple";
编译器将分配2
变量fruit
,这意味着它指向存储字符串apple
的地址2
。
在你的程序中,表达式"banana"
表示程序图像中的一个字符串文字对象,一个字符数组。表达式的值是 char *
或 "pointer to character" 类型。指针指向该数组的第一个字节,字符 'b'
.
你的 char *fruit
变量也有类型 "pointer to character" 并从这个表达式中获取它的初始值:它被初始化为指向数据的指针的副本,而不是数据本身;它仅仅指向 b
.
当您将 "apple"
分配给 fruit
时,您只是将其指针值替换为另一个指针值,因此它现在指向不同的文字数组。
要修改数据本身,您需要一个表达式,例如:
char *fruit = "banana";
fruit[0] = 'z'; /* try to turn "banana" into "zanana" */
根据 ISO C 标准,未定义此行为。 可能 "banana"
数组是只读的,但这不是必需的。
C 实现可以使字符串文字可写,或使其成为一个选项。
(如果您能够修改字符串文字,那并不意味着一切都很好。首先,根据 ISO C,您的程序仍然没有很好地定义:它不可移植。其次,C 编译器允许将具有共同内容的文字合并到同一存储中。这意味着 "banana"
在程序中的两次出现实际上可能是完全相同的数组。此外,字符串文字 "nana"
出现在某处该程序可能是出现在其他地方的数组 "banana"
的后缀;换句话说,共享相同的存储空间。修改文字可能会产生令人惊讶的效果;修改可以出现在其他文字中。)
另外 "static" 和 "read-only" 不是同义词。 C 中的大多数静态存储实际上是可修改的。我们可以创建一个可修改的静态字符数组,其中包含这样一个字符串:
/* at file scope, i.e. outside of any function */
char fruit[] = "banana";
或:
{
/* in a function */
static fruit[] = "banana";
如果我们省略数组大小,它会根据初始化字符串文字自动调整大小,并包括 space 作为空终止字节。在函数中,我们需要static
将数组放入静态存储,否则我们得到一个局部变量。
这些数组可以修改; fruit[0] = 'z'
是定义明确的行为。
此外,在这些情况下,"banana"
不表示字符数组。数组就是变量fruit
; "banana"
表达式只是指示数组初始值的一段语法:
char *fruit = "banana"; // "banana" is an object in program image
// initial value is a pointer to that object
char fruit_array[] = "apple"; // "apple" is syntax giving initial value
fruit
对象是可写的 - 它可以设置为指向不同的字符串文字。
字符串文字 "banana"
和 "apple"
不可写。您可以修改 fruit
以指向字符串文字,但如果您这样做,则不应尝试修改 fruit
指向 的内容:
char *fruit = "banana"; // fruit points to first character of string literal
fruit = "apple"; // okay, fruit points to first character of different string literal
*fruit = 'A'; // not okay, attempting to modify contents of string literal
fruit[1] = 'P'; // not okay, attempting to modify contents of string literal
尝试修改字符串文字的内容会导致未定义的行为 - 您的代码可能会按预期运行,或者您可能会遇到运行时错误,或者可能会发生完全意外的事情。为了安全起见,如果您要定义一个指向字符串文字的变量,您应该声明它 const
:
const char *fruit = "banana"; // can also be written char const *
您仍然可以分配 fruit
以指向不同的字符串:
fruit = "apple";
但是如果你试图修改 fruit
指向的内容,编译器就会对你大喊大叫。
如果你想定义一个只能指向一个特定字符串文字的指针,那么你也可以const
限定指针:
const char * const fruit = "banana"; // can also be written char const * const
这样,如果您尝试写入 fruit
指向的内容,或尝试将 fruit
设置为指向不同的对象,编译器将对您大喊大叫。
当您使用 char *p="banana";
时,字符串 banana 存储在只读内存位置。随后,当您输入 p="apple";
时,字符串 apple 存储在其他内存位置,指针现在指向新的内存位置。
您可以在每次分配后打印 p
来确认这一点。
#include<stdio.h>
int main(void)
{
char *p = "Banana";
printf("p contains address of string constant 'Banana' at 0x%p\n", p);
p="Apple";
printf("p contains address of string constant 'Apple' at 0x%p\n", p);
}
定义 C 字符串时,又名 char
数组,用双引号 "..."
,格式如下:
char * <varName> = "<someString>"
只有数组的元素是不可变的(它们的内容不能改变)。换句话说,<varName>
具有 const char *
类型(指向只读存储器的可变指针)。每次用双引号 <varName> = "<otherString>"
调用赋值运算符时,它都会自动更改指针值。下面的例子应该给出不同可能性的完整概述:
#include <stdio.h>
int main()
{
char * var_1 = "Lorem";
printf("1. %s , %p\n", var_1, var_1); // --> 1. Lorem , 0x400640
var_1 = "ipsu";
printf("2. %s , %p\n", var_1, var_1); // --> 2. ipsu , 0x400652
// var_1[0] = 'x'; // --> Segmentation fault
var_1++;
printf("3. %s , %p\n", var_1, var_1); // --> 3. psu , 0x400653
char var_2[] = {'L', 'o', 'r', 'e', 'm', '[=11=]'};
printf("4. %s , %p\n", var_2, var_2); // --> 4. Lorem , 0x7ffed0fc5381
var_2[0] = 'x';
printf("5. %s , %p\n", var_2, var_2); // --> 5. xorem , 0x7ffed0fc5381
// var_2++; //error: lvalue required as increment operand
char var_3[] = "Lorem";
printf("6. %s , %p\n", var_3, var_3); // --> 6. Lorem , 0x7ffe36a42d5c
// var_3 = "ipsu"; // --> error: assignment to expression with array type
var_3[0] = 'x';
printf("7. %s , %p\n", var_3, var_3); // --> 7. xorem , 0x7ffe36a42d5c
char * const var_4 = "Lorem";
// var_4 = "ipsu"; // --> error: assignment of read-only variable
// var_4[0] = 'x'; // --> Segmentation fault
char const * var_5 = "Lorem";
printf("8. %s , %p\n", var_5, var_5); // --> Lorem , 0x400720
var_5 = "ipsu";
printf("9. %s , %p\n", var_5, var_5); // --> ipsu , 0x400732
// var_5[0] = 'x'; // --> error: assignment of read-only location
const char * var_6 = "Lorem";
printf("10. %s , %p\n", var_6, var_6); // --> 10. Lorem , 0x400760
var_6 = "ipsu";
printf("11. %s , %p\n", var_6, var_6); // --> 11. ipsu , 0x400772
// var_6[0] = 'x'; // --> error: assignment of read-only location
const char const * var_7 = "Lorem"; // clang only --> warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
printf("12. %s , %p\n", var_7, var_7); // --> 12. Lorem , 0x400760
var_7 = "ipsu";
printf("13. %s , %p\n", var_7, var_7); // --> 13. ipsu , 0x400772
// var_7[0] = 'x'; // --> error: assignment of read-only location
char const const * var_8 = "Lorem"; // clang only --> warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
printf("14. %s , %p\n", var_8, var_8); // --> 14. Lorem , 0x400790
var_8 = "ipsu";
printf("15. %s , %p\n", var_8, var_8); // --> 15. ipsu , 0x4007a2
// var_8[0] = 'x'; // --> error: assignment of read-only location
char const * const var_9 = "Lorem";
// var_9 = "ipsu"; // --> error: assignment of read-only variable
// var_9[0] = 'x'; // --> error: assignment of read-only location
const char var_10[] = {'L', 'o', 'r', 'e', 'm', '[=11=]'};
// var_10[0] = 'x'; // --> error: assignment of read-only location
// var_10++; // --> error: lvalue required as increment operand
char const var_11[] = {'L', 'o', 'r', 'e', 'm', '[=11=]'};
// var_11[0] = 'x'; // --> error: assignment of read-only location
// var_11++; // --> error: lvalue required as increment operand
const char var_12[] = "Lorem";
// var_12[0] = 'x'; // --> error: assignment of read-only location
// var_12++; // --> error: lvalue required as increment operand
char const var_13[] = "Lorem";
// var_13[0] = 'x'; // --> error: assignment of read-only location
// var_13++; // --> error: lvalue required as increment operand
return 0;
}
此代码已在 GCC、Clang 和 Visual Studio 上测试。
基本上有3种可能:
不可变指针,可变内容
char <varName>[] = {'L', 'o', 'r', 'e', 'm', '[=17=]'};
char <varName>[] = "Lorem";
指针可变,内容不可变
char * <varName> = "Lorem";
char const * <varName> = "Lorem";
const char * <varName> = "Lorem";
const char const * <varName> = "Lorem";
char const const * <varName> = "Lorem";
不可变指针,不可变内容
char * const <varName> = "Lorem";
char const * const <varName> = "Lorem";
const char * const <varName> = "Lorem";
const char <varName>[] = {'L', 'o', 'r', 'e', 'm', '[=27=]'};
char const <varName>[] = {'L', 'o', 'r', 'e', 'm', '[=28=]'};
const char <varName>[] = "Lorem";
char const <varName>[] = "Lorem";
结论:
<typing> <varName>[] = <string>
总是 returns 不可变指针,内容的可变性独立于<array>
格式("Lorem"
或{'L', 'o', 'r', 'e', 'm', '[=34=]'}
)<typing> * <varName> = "someString"
始终returns不可变内容<typing> * const <varName> = "someString"
总是returns不可变内容和指针char const <other>
、char const <other>
、const char const <other>
和char const const <other>
始终创建不可变内容。
我试图详细总结 C 的数组行为 here。