简体   繁体   English

声明没有const的C风格字符串是不是很糟糕?如果是这样,为什么?

[英]Is it bad to declare a C-style string without const? If so, why?

Doing this in C++ 在C ++中执行此操作

char* cool = "cool";

compiles fine, but gives me a warning: 编译好,但给了我一个警告:

deprecated conversion from string constant to char*. 不推荐将字符串常量转换为char *。

I would never willfully use a C-style string over std::string , but just in case I'm asked this question: 我永远不会故意在std::string使用C风格的std::string ,但以防万一我被问到这个问题:

is it bad practice to declare a C-style string without the const modifier? 如果没有const修饰符声明一个C风格的字符串是不好的做法? If so, why? 如果是这样,为什么?

Yes, this declaration is bad practice, because it allows many ways of accidentally provoking Undefined Behavior by writing to a string literal, including: 是的,这个声明是不好的做法,因为它允许通过写入字符串文字来多次意外地激发未定义的行为,包括:

cool[0] = 'k';
strcpy(cool, "oops");

On the other hand, this is perfectly fine, since it allocates a non-const array of chars: 另一方面,这非常好,因为它分配了一个非const的字符数组:

char cool[] = "cool";

Yes, in C++ you should always refer to string literals with variables of type const char * or const char [N] . 是的,在C ++中,您应该始终使用const char *const char [N]类型的变量引用字符串文字。 This is also best practice when writing new C code. 这也是编写新C代码时的最佳实践。

String literals are stored in read-only memory, when this is possible; 当可能时,字符串文字存储在只读存储器中; their type is properly const -qualified. 它们的类型是否正确const -qualified。 C, but not C++, includes a backward compatibility wart where the compiler gives them the type char [N] even though they are stored in read-only memory. C,但不是C ++,包括向后兼容性的疣, 即使它们存储在只读存储器中,编译器也会为它们提供char [N]类型。 This is because string literals are older than the const qualifier. 这是因为字符串文字比const限定符旧。 const was invented in the run-up to what's now called "C89" -- the earlier "K&R" form of the language did not have it. const是在现在被称为“C89”之前发明的 - 早期的“K&R”形式的语言没有它。

Some C compilers include an optional mode in which the backward compatibility wart is disabled, and char *foo = "..."; 一些C编译器包括一个可选模式,其中禁用向后兼容性疣,并且char *foo = "..."; will get you the same or a similar diagnostic that it does in C++. 将为您提供与C ++相同或类似的诊断。 GCC spells this mode -Wwrite-strings . GCC拼写这种模式-Wwrite-strings I highly recommend it for new code; 我强烈推荐它用于新代码; however, turning it on for old code is liable to require an enormous amount of scutwork for very little benefit. 然而,为旧代码打开它可能需要大量的scutwork才能获得很少的好处。

It's bad. 这不好。 It's very bad. 这很糟糕。 To the point this isn't possible to do anymore in C++11. 到目前为止,这在C ++ 11中是不可能的。

Modifying the memory of a string literal is undefined behaviour. 修改字符串文字的内存是未定义的行为。

First, char* cool = "cool"; 首先, char* cool = "cool"; is not standard C++. 不是标准的C ++。 A string literal has the type of const char[n] . 字符串文字的类型为const char[n] So the above line of code breaks const-correctness and should not compile. 所以上面的代码行打破了const-correctness,不应该编译。 Some compilers like GCC allow this but issue a warning as it is a hold over from C. MSVC will issue a error since it is a error. 像GCC这样的一些编译器允许这样做,但发出警告,因为它是C的保留.MSVC会发出错误,因为它是一个错误。

Second, why not let the compiler work for you? 第二,为什么不让编译器为你工作? If it is marked const then you will get a nice compiler error if you accidentally try to modify it. 如果它被标记为const那么如果你不小心尝试修改它,你将得到一个很好的编译器错误。 If you do not then you can get a really nasty run time error which can be much harder to find. 如果你不这样做,你可以得到一个非常讨厌的运行时错误,这可能更难找到。

It is bad because string constants might be contained only once per binary (keyword: stringtable, .strtab ). 这很糟糕,因为字符串常量每个二进制文件只能包含一次(关键字:stringtable, .strtab )。 Eg in 例如

char *cool = "cool";
char *nothot = "cool";

both variables can point to the same memory location. 两个变量都可以指向相同的内存位置。 Modifying the contents of one of them might alter the other too, so that after 修改其中一个的内容也可能会改变另一个,所以之后

strcpy(nothot, "warm");

your cool becomes "warm". 你的cool变得“温暖”。

In short, it is undefined behaviour. 简而言之,它是未定义的行为。

It is a string literal, therefore it should be constant as memory might be located in read only section. 它是一个字符串文字,因此它应该是常量,因为内存可能位于只读部分。 If you have char cool[] = "cool"; 如果你有char cool[] = "cool"; then it's not a problem, the memory is yours. 那不是问题,记忆是你的。

char* cool = "cool" char * cool =“cool”

"cool" will be stored in a read only block (generally in data segment) that is shared among functions. “cool”将存储在函数之间共享的只读块(通常在数据段中)中。 If you try to modify the string "cool" by the point cool you will get a error such as segment error when the program is running. 如果您尝试通过酷点修改字符串“cool”,则会在程序运行时出现错误,例如段错误。 If you use const char* cool = "cool" , you will get a error when compile if you try to modify the string. 如果使用const char* cool = "cool" ,如果尝试修改字符串,则在编译时会出错。
You can read this page for more information http://www.geeksforgeeks.org/storage-for-strings-in-c/ 您可以阅读此页面以获取更多信息http://www.geeksforgeeks.org/storage-for-strings-in-c/

为字符串编写const是一个很好的做法(特别是当你使用字符串文字时),但在C中它几乎没有区别,它会在c ++中向你发出警告但在c中没有警告,还记得一些编译器假设.c扩展只是作为c但.C作为c ++,所以在这些点上要小心。另外,在字符串的情况下使用const是一个好习惯,所以错误地你不要改变字符串或尝试改变存储的字符串文字在只读内存中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM