为什么从字符串常量到'char *'的转换在C中有效但在C ++中无效


162

C ++ 11标准(ISO / IEC 14882:2011)在§ C.1.1

char* p = "abc"; // valid in C, invalid in C++

对于C ++,因为指向字符串文字的指针是有害的,因为任何对其进行修改的尝试都将导致崩溃,这是有害的。但是为什么在C语言中有效呢?

C ++ 11还说:

char* p = (char*)"abc"; // OK: cast added

这意味着如果将强制类型转换添加到第一条语句中,它将变为有效。

为什么强制转换使第二条语句在C ++中有效,它与第一条语句有何不同?还是有害吗?如果是这样,为什么标准说没问题?


3
C ++ 11不允许第一个。我不知道为什么C char[]首先要做字符串文字的类型。第二个是const_cast变相。
克里斯

4
如果更改此规则,那么太多的遗留C代码将被破坏。
Paul R

1
请引用标准说第二的地方的文字OK
Nawaz 2014年

13
C语言比以前有字符串文字const,因此不一定const
Casey 2014年

2
C和C ++允许您将几乎所有类型都转换为另一种类型。这并不意味着这些演员表是有意义且安全的。
思源任

Answers:


206

在C ++ 03之前,您的第一个示例是有效的,但是使用了不建议使用的隐式转换-字符串文字应被视为type char const *,因为您无法修改其内容(不会引起未定义的行为)。

从C ++ 11开始,已经弃用了隐式转换,因此,依赖它的代码(如您的第一个示例)应该不再编译。

您已经注意到一种允许代码编译的方法:尽管隐式转换已被删除,但显式转换仍然有效,因此可以添加强制类型转换。我不是,但是,考虑这个“固定”的代码。

真正修复代码需要将指针的类型更改为正确的类型:

char const *p = "abc"; // valid and safe in either C or C++.

关于为什么在C ++中允许使用它(现在仍然在C中使用):仅因为存在许多依赖于该隐式转换的代码,并且在标准委员会看来,破坏该代码(至少在没有任何正式警告的情况下)似乎像一个坏主意。


8
@rullof:非常危险的是它没有提供任何有意义的灵活性,至少对于(完全)关心可移植性的代码而言。写入字符串文字通常会使您的程序在现代OS上中止,因此允许代码在此处尝试写入不会增加任何有意义的灵活性。
杰里·科芬

3
此答案中给出的代码段char const *p = "abc";是“在C C ++ 中有效且安全”,而不是“在C C ++ 中有效且安全”。
Daniel Le

4
@DanielLe这两个句子的含义相同
Caleth

3
哦,我的主![将舌头牢牢地插在脸颊上]对不起,但是“或”是正确的术语。可以将代码编译为C或C ++,但不能同时编译为C和C ++。您可以选择任何一个,但必须做出选择。您不能一次拥有两个。[恢复正常的舌头操作]。
杰里·科芬

2
不,这两者都是最清晰,最正确的措词。 /或者也恰好传达了正确的含义,但是在技术上还不清楚。 无可辩驳是错误的(A或B不等于A和B)。
Apollys

15

由于历史原因,它在C中有效。C通常会指定字符串文字的类型为,char *而不是const char *,尽管它通过说实际上不允许您对其进行修饰来对其进行限定。

使用强制转换时,实际上是在告诉编译器您知道比默认类型匹配规则更好的知识,并且它使分配正常。


3
char[N],已更改为const char[N]。它附带有尺寸信息。
克里斯2014年

1
在C类型的字符串中,文字char[N]不是(char*例如"abc"char[4]
Grijesh Chauhan 2014年

2

您也可以使用strdup

char* p = strdup("abc");
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.