【问题标题】:Is there a difference between const char * const and const char []?const char * const 和 const char [] 之间有区别吗?
【发布时间】:2013-04-23 16:40:33
【问题描述】:

考虑以下两行代码:

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

对于指针定义,"Hello" 字符串字面量本质上是不可变,但ptr 变量本身可以改变并持有不同的地址。

对于数组定义,"Hello" 字符串文字被复制到数组的位置,但arr 不能指向不同的位置;但是,数组保存的字符串是可变的,因此可以更改。

现在考虑以下两行代码:

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

这里,由于const char 限定符,两个字符串都是不可变的——不过更有趣的是:将ptr 定义为常量指针,它不能指向不同的地址。

这两行代码会导致相同的行为吗?如果最终效果相同,在实现上是否存在理论上的差异——例如,指针方法是否为匿名数组分配内存来保存指针本身之外的字符串,而数组方法只为一个数组?

【问题讨论】:

  • 区别:1.数组不是指针,2.指针不是数组,3.sizeof()

标签: c arrays pointers constants c99


【解决方案1】:

这里有一些区别。

首先,这可能适用于某些实现,因为指针可以指向相同的内存:

const char * const ptr1 = "Hello";
const char * const ptr2 = "Hello";

ptr1 == ptr2;

但是用数组形式就不行了。

无论如何,真正的区别在于它们的类型不同。特别是,char[] 版本在数组类型中保留了它的大小。所以sizeof(arr)给你的是数组的大小,而不是一个指针,你也可以创建指向arr的数组的指针。

【讨论】:

  • 关于“某些实现”,在 Visual Studio 中有一个“字符串池”选项(/GF 编译器参数)。默认情况下它通常是关闭的,但是如果你启用它,那么编译器会在你的程序中找到所有相等的字符串文字并将它们变成一个单一的常量,从而节省一些内存。这将均衡 ptr1 和 ptr2。
【解决方案2】:

两者之间有区别:它们的地址。具有相同内容的所有字符串文字可能(但不一定)指向相同的地址。数组定义(如果它在函数范围内)定义了一个新对象,该对象不同于字符串文字,也不同于具有相同内容的任何其他此类对象。因此地址必须不同。

如果您的函数是递归的,情况尤其如此。然后你的函数的所有嵌套调用都会定义一个新变量,每个变量都有不同的地址。

【讨论】:

    【解决方案3】:
    const char *ptr = "Hello";
    

    这将 ptr 声明为 const 指向字符的指针,初始化为指向字符串文字“Hello”。所指出的 NOT 是否具有 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 声明为 char 的 const 数组 [6],再次初始化为 {'H', 'e', 'l', 'l', 'o', '\0'}

    所有不同,但我看到其他人已经为您的问题提供了更好的答案。

    【讨论】:

    • 如果我使用const char *ptr,理论上我可以使用第二个指针来访问相同的内存位置来修改内存吗? const char arr[] 也是这样吗?
    • 您总是可以使用第二个指针来丢弃类型限定,例如constness。但是,这是一种违规行为,有时所指向的内容实际上是不可修改的(导致程序崩溃),任何中途可行的编译器都会对此发出警告。
    【解决方案4】:

    好吧,&ptr&arr 至少存在一个语义差异,它们会产生不同的类型——一种是指向指针的指针,另一种是指向数组的指针。这是否真的在任何地方很重要 当然取决于你如何使用它们。检查编译器的输出机器代码以获得特定结果。

    【讨论】:

    • 我无法理解 pointer-to-pointerpointer-to-array 之间的区别。 sizeof(*(&arr)) 会产生数组的大小吗?
    • 是的,我想是的。你应该可以试试看。我建议您查看section 6 of the comp.lang.c FAQ 以开始使用。
    • 是的,我认为这部分解释得很好:c-faq.com/aryptr/ptrtoarray.html
    【解决方案5】:

    对于数组定义,"Hello" 字符串文字被复制到数组的位置,但 arr 不能指向不同的位置

    字符串不会复制到数组中,它不会像字符串字面量那样创建和存储在只读位置(可以隐式转换为指针),但它只是一种简写形式

    char arr[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
    

    正如标准所说:

    字符类型的数组可以由字符串文字或 UTF-8 字符串文字初始化,可选用大括号括起来。

    而且数组不会“指向”,arrays are not pointers

    这两行代码会导致相同的行为吗?

    不,它们有完全不同的类型,出于同样的原因。

    除了指针本身之外,指针方法是否为匿名数组分配内存来保存字符串,而数组方法只为数组分配内存?

    是的,如果使用相同的字符串字面量,“匿名”创建的数组可以在另一个地方再次使用(但在一般情况下,您无法知道编译器实际做了什么):

    如果这些数组的元素具有适当的值,则不确定这些数组是否不同。

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

    【讨论】:

      猜你喜欢
      • 2018-11-05
      • 2011-02-25
      • 2010-10-27
      • 2011-03-07
      • 1970-01-01
      • 1970-01-01
      • 2012-12-26
      • 2014-02-15
      相关资源
      最近更新 更多