const char * const和const char []有什么区别?

3

考虑以下两行代码:

const char *ptr = "Hello";
char arr[] = "Hello";

对于指针的定义,"Hello" 字符串字面量基本上是不可变的,但 ptr 变量本身可以改变并保存不同的地址。
对于数组的定义,"Hello" 字符串字面量被 复制 到数组的位置,但是 arr 不能 指向另一个位置;但是,数组所持有的字符串是可变的,因此可以更改。
现在考虑以下两行代码:
const char * const ptr = "Hello";
const char arr[] = "Hello";

在这里,由于“const char”限定符的影响,两个字符串都是不可变的——更有趣的是:如果将“ptr”定义为常量指针,则它不能指向不同的地址。
这两行代码会产生相同的行为吗?如果最终效果相同,那么在实现上是否存在理论上的差异——例如,指针方法是否会分配内存来容纳匿名数组以保存字符串,而数组方法仅仅分配内存用于数组本身?

8
区别:1. 数组不是指针,2. 指针不是数组,3. sizeof() - user529758
5个回答

4
这里有几个不同之处。
首先,这在某些实现上可能成立,因为指针可以指向相同的内存:
const char * const ptr1 = "Hello";
const char * const ptr2 = "Hello";

ptr1 == ptr2;

但使用数组形式是不可能实现的。

不过,真正的区别在于它们的类型不同。特别是,char[] 版本保留了数组类型中的大小。因此,sizeof(arr) 给出的是数组的大小,而不是指针,并且您还可以创建指向数组的指针来访问 arr


关于“某些实现”,在Visual Studio中有一个“字符串池”选项(/GF编译器参数)。通常情况下默认关闭,但如果您启用它,则编译器将查找程序中所有相等的字符串文字并将它们转换为单个常量,从而节省一些内存。 这将使ptr1和ptr2相等。 - Parallel Universe

3

两者之间有一个不同之处:它们的地址。所有具有相同内容的字符串字面量可能(但不一定)指向相同的地址。如果数组定义在函数范围内,则定义了一个新对象,与字符串字面量不同,并且与任何具有相同内容的其他对象也不同。因此,这些地址必须是不同的。

如果您的函数是递归的,那么这将特别成立。然后,您函数的所有嵌套调用都将定义一个新变量,每个变量的地址都不同。


3
const char *ptr = "Hello";

这个声明将ptr声明为一个指向char的const指针,初始化为指向字符串字面值"Hello"。 所指向的内容不是const类型,尽管实现允许将其放置在只读内存中。

char arr[] = "Hello";

这声明了一个数组 arr,类型为 char[6],并初始化为 {'H', 'e', 'l', 'l', 'o', '\0'}
const char * const ptr = "Hello";

这将 ptr 声明为一个 const 指向 const char 的指针,其初始值为指向字符串常量 "Hello"。虽然该指针被声明为指向 const 内存,但字符串常量本身仍然没有 const 类型,尽管实现仍然可以将其放置在只读内存中。
const char arr[] = "Hello";

这将 arr 声明为一个包含 6 个 char 的 const 数组,再次初始化为 {'H', 'e', 'l', 'l', 'o', '\0'}

虽然有所不同,但我看到其他人已经提供了更好的答案来回答你的问题。


如果我使用const char *ptr,理论上我可以使用第二个指针访问相同的内存位置来修改内存吗?这也适用于const char arr[]吗? - Vilhelm Gray
1
您总是可以使用第二个指针来丢弃类型限定符,例如 const。 这是一种违规行为,有时指向的内容确实是不可修改的(导致程序崩溃),任何半可用的编译器都会发出警告。 - This isn't my real name

2

嗯,至少有一个语义上的区别是&ptr&arr会产生不同类型的结果 - 一个是指向指针的指针,另一个是指向数组的指针。当然,这是否真的有关系取决于你如何使用它们。请检查编译器输出的机器代码以获取具体结果。


我很难理解“指向指针”和“指向数组”的区别。sizeof(*(&arr))会返回数组的大小吗? - Vilhelm Gray
1
是的,我认为可以。你应该尝试一下并查看结果。我建议先查看comp.lang.c FAQ的第6节来开始。 - Carl Norum
是的,我认为这个部分解释得非常好:http://c-faq.com/aryptr/ptrtoarray.html - Vilhelm Gray

1
对于数组定义,字符串文字“Hello”被复制到数组的位置,但arr不能指向不同的位置。
该字符串没有被复制到数组中,也没有在只读位置创建和存储(可以隐式转换为指针的)字符串字面量,而只是一个简写形式。
char arr[] = { 'H', 'e', 'l', 'l', 'o', '\0' };

按照标准:

字符类型的数组可以通过字符字符串字面值或UTF-8字符串字面值进行初始化,可以选择用大括号括起来。

而数组不会“指向”,数组不是指针

这两行代码会产生相同的行为吗?

不会,它们具有完全不同的类型,原因相同。

指针方法是否为匿名数组分配内存以容纳指针本身之外的字符串,而数组方法仅为数组分配内存?

是的,“匿名”创建的数组如果使用相同的字符串字面值,则可以在另一个地方再次使用(但通常情况下您无法知道编译器实际执行的操作):

未指定这些数组是否不同,只要它们的元素具有适当的值即可。

同样,第二行只是语法糖来初始化数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接