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

时间:2016-07-25 17:37:17

标签: c++ c c-strings

在C ++中执行此操作

char* cool = "cool";

编译得很好,但是给了我一个警告:

  

已弃用从字符串常量转换为字符*。

我永远不会故意在std::string上使用C风格的字符串,但以防万一我被问到这个问题:

在没有const修饰符的情况下声明C风格的字符串是不好的做法?如果是这样,为什么?

8 个答案:

答案 0 :(得分:59)

是的,这个声明是不好的做法,因为它允许通过写入字符串文字来多次意外地激发未定义的行为,包括:

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

另一方面,这非常好,因为它分配了一个非const的字符数组:

char cool[] = "cool";

答案 1 :(得分:16)

是的,在C ++中,您应始终使用类型为const char *const char [N]的变量引用字符串文字。这也是编写新C代码时的最佳实践。

当可能时,字符串文字存储在只读存储器中;他们的类型合适const - 合格。 C,但不是C ++,包括向后兼容性疣,编译器为它们提供类型char [N] ,即使它们存储在只读内存中。这是因为字符串文字比const限定符旧。 const是在现在被称为“C89”之前发明的 - 早期的“K& R”形式的语言没有它。

某些C编译器包含一个可选模式,其中禁用向后兼容性wart,char *foo = "...";将获得与C ++中相同或类似的诊断。 GCC拼写此模式-Wwrite-strings。我强烈推荐它用于新代码;但是,为旧代码打开它可能需要大量的scutwork才能获得很少的好处。

答案 2 :(得分:14)

这很糟糕。这很糟糕。到目前为止,这在C ++ 11中是不可能的。

修改字符串文字的内存是未定义的行为。

答案 3 :(得分:13)

首先,char* cool = "cool";不是标准C ++。字符串文字的类型为const char[n]。所以上面的代码行打破了const-correctness,不应该编译。像GCC这样的一些编译器允许这样做,但发出警告,因为它是C的保留.MSVC会发出错误,因为它是一个错误。

其次,为什么不让编译器为你工作?如果它被标记为const,那么如果您不小心尝试修改它,您将得到一个不错的编译器错误。如果你不这样做,你可能会得到一个非常讨厌的运行时错误,这可能更难找到。

答案 4 :(得分:7)

这很糟糕,因为字符串常量每个二进制文件只能包含一次(关键字:stringtable,.strtab)。例如。在

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

两个变量都可以指向相同的内存位置。修改其中一个的内容也可能会改变另一个,所以在

之后
strcpy(nothot, "warm");

你的cool变得温暖"。

简而言之,这是未定义的行为。

答案 5 :(得分:6)

它是一个字符串文字,因此它应该是常量,因为内存可能位于只读部分。如果你有char cool[] = "cool";那么这不是问题,那就是你的记忆。

答案 6 :(得分:2)

  

char * cool =“cool”

“cool”将存储在函数之间共享的只读块(通常在数据段中)中。如果您尝试通过酷点修改字符串“cool”,则会在程序运行时出现错误,例如段错误。如果您使用const char* cool = "cool",则在编译时如果尝试修改字符串,则会出错 您可以阅读此页面以获取更多信息http://www.geeksforgeeks.org/storage-for-strings-in-c/

答案 7 :(得分:0)

为字符串编写const是一个好习惯(特别是当您使用字符串文字时),但是在C语言中几乎没有什么不同,它会在c ++中向您发出警告,而在c中则没有警告,还请记住一些编译器假定。 c扩展名与c相同,而.C与c ++相同,因此在这种情况下要格外小心。否则,在字符串的情况下使用const是一个好习惯,因此错误地不要更改字符串或尝试更改字符串文字存储在只读存储器中。