C字符串数组初始化-这是可变的

C-String array initialization - is this mutable?

本文关键字:字符串 数组 初始化      更新时间:2023-10-16

可能重复:
修改C字符串常量
指向常量字符与字符数组与标准::字符串的指针

我知道我可能在这个问题上孤注一掷,但我有点困惑,我还没有在SO或谷歌上找到确切的答案(我相信这是对的——关于C字符串的信息太多了,无法筛选)。另外,我把它标记为C++,因为这就是我感兴趣的地方,尽管我们谈论的是C风格的字符串。

在这种情况下:

char const a*  = "hello";
char const b[] = "goodbye";

我本以为"hello"answers"再见"都是不可变的字符串,因为它们来自应该衰减为char const*的字符串文本。

不过,我已经看到,在这种特殊的情况下,如果从b数组中去掉了constness,那么更改"hello"将是未定义的,而更改"再见"则可以。

我假设字符串在b的情况下是可变的,因为它存储在用户定义的数组中。

在这种情况下,你好和再见有区别吗由于某些原因,在给定此示例的情况下,再见不是字符串文字。此外,如果再见不是字符串文字,我能假设它没有保存在全局内存中,并且在编译时对它的唯一引用是留在用户数组单元格中的引用吗?

第一个创建一个指针,指向字符串文本"hello",该文本可能存储在程序的可执行映像中的不可写内存中。即使不是,也不允许修改该数组的内容。

第二个创建一个自动数组1(在堆栈上(通常,但这是实现定义的)),并用字符串"goodbye"初始化它。它相当于

char const b[] = {'g', 'o', 'o', 'd', 'b', 'y', 'e', 0};

因此,虽然"goodbye"是不可变的,因为它是一个字符串文字,是char const[8]并存储在不可写的内存中,但数组b是一个自动的1数组,它不可变,因为您将其标记为const,但您可以从变量声明中删除const,使数组的内容可变。您只是用数组"goodbye"的内容初始化数组的内容

不允许修改其中任何一个,因为它们都是const char[],但第二个可以更改为char[]以使其可变,而第一个不能。

查看此答案以了解更多信息:https://stackoverflow.com/a/9106798/726361


1正如R.Martinho Fernandes在评论中指出的那样,如果语法T x[] = ...在命名空间范围内,它也可以创建一个静态数组(不是自动的,而是静态的(通常在可执行映像中,但这是实现定义的),否则它只是一个自动数组。

字符串文字的类型为char const[N];当然,这种类型的名称可以衰减为CCD_ 13。

现在:

  1. char数组可以通过字符串文字(8.5.2/1)进行初始化,并且由于不能以其他方式复制或分配数组,因此这种初始化实现了复制。您可以随心所欲地使用新的可变数组。

    char str[6] = "hello";
    
  2. 相反,初始化指针时,您获得的指针是字符串文字的不可变数组类型衰减的结果。

    char const* str = "hello";
    

    这里没有新的数组。只是复制一个指向现有不可变数据的指针。

它们是不同的。a指向一个无法更改的字符串文字。但是,b是一个使用给定字符串初始化的字符数组。假设const已删除,则可以更改b的内容。

是的,它们不同。

字符串文字本身("hello""goodbye")确实是不可变的。但是,当您访问b时,您并没有访问原始的"goodbye"。您使用的代码声明了一个完全独立的数组b,它只是用字符串"goodbye"初始化的。您的'b'完全独立于原始字符串文字"goodbye"。您的b是该字符串文字的副本。您的"b"是不可变的唯一原因是您显式包含在其声明中的const。删除const,您的b将变得完全可变,就像任何普通数组一样。

至于您的"a",它是一个直接指向原始字符串文本"hello"的指针。当然,它是不可变的。

这两个选项都是不可变的,但这并不是因为它们是从字符串文字创建的。它们是不可变的,因为变量声明中有const关键字。

您还可以编写char c[] = "string_c";,并创建文字string_c的可变副本(名为c)。

在您关于删除b常量的示例中,在某些情况下,这可能会出现,但就标准而言,这仍然是非法的。只有真正非常量的对象才能发生突变。