C++11 字符数组初始化和字符串字面量
Posted
技术标签:
【中文标题】C++11 字符数组初始化和字符串字面量【英文标题】:C++11 char array intializations and string literals 【发布时间】:2021-07-02 18:09:53 【问题描述】:在 C++11 中,char
指针不能直接初始化为字符串字面量。
在早期版本的 C++ 中,我可以毫无问题地做到这一点。
如果允许以下代码:
char arr[] = "Hello";
char *p_str1 = arr; //allowed
那为什么下面的代码不允许呢?
char *p_str3 = "Hello"; //Not allowed
注意:我知道添加 const
会解决问题。但我需要知道原因。
【问题讨论】:
恕我直言,错误消息中的原因很清楚。第二个和第一个类似,但const char arr[] = "Hello";
.
@S.M.需要知道第一个与第二个有何不同
C相关问题:C: differences between char pointer and array
@CEPB 我不知道有任何 C++ 实现会为这两种情况执行堆分配。
@CEPB 对您的评论的编辑使它变得更加错误,而不是更少。这与跟踪动态内存分配的能力无关。
【参考方案1】:
char arr[] = "Hello"
将字符串文字"Hello"
的可修改副本存储在字符数组arr
中。 p_str1
是指向那个数组的指针,数据是可修改的,所以指针不需要是const
。
char *p_str3 = "Hello"
是直接指向只读字符串文字的指针。指针不拥有字符串文字,通常这些都存储在内存的一些只读部分中,无论哪种方式您都可以访问数据,但您不能修改它,所以const
指针强制避免在运行时出现不希望出现的问题。
C++ 标准不允许非常量指针指向不可修改的数据。这是幸运的,因为它通过尝试修改它来避免未定义的行为,就像在不存在此规则的 C 中经常发生的那样。
在 C++03 中使用非常量 char
指针仍然是合法的(可能是出于兼容性原因),当它被弃用时,在 C++11 之后它被禁止,但据我所知,尝试修改这些字符串文字总是未定义的行为。
【讨论】:
好的。不过只是一个问题。那么在 C++11 之前,这部分不是只读的吗? 不,它可能仍然是只读的。允许指向字符串文字的非常量指针是非强制错误的常见来源,因此标准编写者决定硬着头皮将其正式定为非法。 @SumaiyaA,我误解了你的问题,它永远无法修改,const
规则的实施是为了避免尝试修改它所产生的问题。
@user4581301 是的,这是我的主要困惑点。感谢您清除该部分始终是只读的,但修改它会导致错误。所以现在受到了正确的限制。
我不说“始终为只读” 我不相信标准要求它是只读的,只是它可能是只读的记忆。我不擅长标准解析和语言法,但总的来说 C++ 标准不喜欢指定这样的细节。只有在 C++20 中,2s Compliment 在成为事实上的标准几十年后才成为一项要求。我相信会有一些奇怪的系统可以修改文字,但我怀疑你会在实验室之外看到一个。我从来没有见过。【参考方案2】:
因为C++明白字符串常量会被存储在不可修改的内存中,所以必须标记为const
。在许多编译器中,它存储在只读的 data segment 中。
任何修改该字符串的尝试都可能导致分段错误。
在第一种情况下,您实际上是在复制到本地数组。这是可以修改的。
【讨论】:
第一种方法与方法 2 有何不同。需要明确。那么字符串常量不会存储在不可修改的内存中? 在第一种情况下,您说的是“请创建一个包含以下内容副本的本地数组”,并且在大多数编译器上存储在堆栈中。 任何修改该字符串的尝试都可能导致分段错误。 或更糟。我记得邪恶而神秘的“巴士错误”。以上是关于C++11 字符数组初始化和字符串字面量的主要内容,如果未能解决你的问题,请参考以下文章