用C++实现这个
char* cool = "cool";
编译没有问题,但是会给我一个警告:
从字符串常量转换为 char* 是不赞成的。
我从不会有意地使用 C 风格的字符串而不是 std::string
,但以防万一我被问到这个问题:
声明一个没有带有 const
修饰符的 C 风格字符串,这是坏习惯吗?如果是,为什么?
用C++实现这个
char* cool = "cool";
编译没有问题,但是会给我一个警告:
从字符串常量转换为 char* 是不赞成的。
我从不会有意地使用 C 风格的字符串而不是 std::string
,但以防万一我被问到这个问题:
声明一个没有带有 const
修饰符的 C 风格字符串,这是坏习惯吗?如果是,为什么?
是的,这种写法是不好的实践,因为它允许通过写入字符串字面值来无意中引发多种未定义行为,包括:
cool[0] = 'k';
strcpy(cool, "oops");
另一方面,这是完全可以的,因为它分配了一个非 const 的字符数组:
char cool[] = "cool";
char *cool = "cool";
、const char *cool = "cool";
、char cool[] = "cool";
和const char cool[] = "cool";
,但不适用于char cool = "cool\0";
,因为其中六个字符中只有前五个形成了C风格字符串。即使在Google的帮助下,我也无法找到其他定义。 - user743382char cool[] = "cool";
和 char* cool = "cool";
有什么不同?我本以为它们基本上是相同的。 - Dave Cousineau是的,在C++中,您应该始终使用const char *
或const char [N]
类型的变量引用字符串字面值。这也是编写新的C代码时的最佳实践。
字符串字面值存储在只读内存中,当可能时;它们的类型被正确地加上了const
限定符。C语言(但不是C++)包括了一个向后兼容的瑕疵,其中编译器将它们的类型设置为char [N]
,即使它们存储在只读内存中也是如此。这是因为字符串字面值比const
限定符更古老。 const
是在现在被称为“C89”的版本中开发出来的,而最初的“K&R”语言形式中没有它。
一些C编译器包括一个可选模式,在该模式下禁用了向后兼容的瑕疵,char *foo = "...";
将会得到与C++类似的诊断结果。 GCC将此模式命名为-Wwrite-strings
。 我强烈建议对于新代码使用它;但是,为旧代码启用它可能需要大量的无用功。
-Wwrite-strings
选项会使你在调用带有char *
参数的库函数时去掉const
修饰符。在这种情况下,我更喜欢不使用该选项。 - yellowantphilconst char *
)。 - zwolexecvp
中找到(查找表格),但你可能还需要阅读http://c-faq.com/ansi/constmismatch.html,以了解他们所说的“C语言限制”究竟有多糟糕。 - zwol很糟糕,非常糟糕。在C++11中这已经不可能再做了。
修改字符串字面量的内存是未定义的行为。
首先,char* cool = "cool";
不是标准的C++语法。字符串字面值的类型为const char[n]
。因此上述代码违反了const正确性,不应该编译。一些编译器,例如GCC允许这样写但会发出警告,因为这是C遗留下来的问题。MSVC将发出错误提示,因为它是错误的。
其次,何不让编译器帮你完成工作呢?如果对其进行标记为const
,那么如果您意外地尝试修改它,将会得到一个很好的编译器错误。如果没有这样做,则可能会发生非常严重的运行时错误,这可能更难以找到。
这是不好的,因为字符串常量可能只在二进制文件中出现一次(关键字:stringtable,.strtab
)。例如,在
char *cool = "cool";
char *nothot = "cool";
两个变量可能指向同一内存位置。修改其中一个变量的内容可能会改变另一个变量的值,因此在此之后
strcpy(nothot, "warm");
你的酷
变成了“温暖”。
简而言之,这是未定义行为。
这是一个字符串字面量,因此应该将其作为常量,因为内存可能位于只读部分。如果您有char cool[] = "cool";
,那么就没有问题了,内存属于您。
char* cool = "cool"
字符串“cool”将被存储在只读块(通常在数据段中),该块在函数间共享。如果您尝试通过指针cool修改字符串“cool”,则在程序运行时会出现诸如段错误之类的错误。如果您使用const char* cool = "cool"
,则在编译时尝试修改字符串时会出现错误。
您可以阅读此页面以获取更多信息:http://www.geeksforgeeks.org/storage-for-strings-in-c/
对于字符串(尤其是使用字符串字面量时),写const是一个好习惯,但在 C 中几乎没有什么差别。在C++中会产生警告,但在C中不会。此外,请记住,一些编译器将 .c 扩展名简单地视为C,而 .C 则为 C++,因此在这些点上要小心。否则,使用 const 来处理字符串的大小写是一个好习惯,这样您不会错误地更改字符串或尝试更改存储在只读内存中的字符串字面量。