4
char* foo = "fpp"; //compile in vs 2010 with no problem

我虽然字符串文字是 const char* 类型。
并且 const 类型不能分配给非常量类型。
所以我希望上面的代码会失败或者我错过了什么?

编辑:对不起,我完全忘记了编译器也会抛出警告。
我一直在看错误列表。
我忘记检查了。

Edit2:我将我的项目警告级别设置为 EnableAllWarnings (/Wall) 并且没有关于此的警告。
所以我的问题仍然有效。

4

7 回答 7

6

C++03 弃用[Ref 1]const使用不带关键字的字符串文字。

[参考 1] C++03 标准:§4.2/2

不是宽字符串文字的字符串文字 (2.13.4) 可以转换为“pointer to char”类型的右值;宽字符串文字可以转换为“指向 wchar_t 的指针”类型的右值。无论哪种情况,结果都是指向数组第一个元素的指针。仅当存在显式适当的指针目标类型时才考虑这种转换,而不是当一般需要从左值转换为右值时。[注意:此转换已弃用. 见附录 D。] 为了在重载决议 (13.3.3.1.1) 中排名,这种转换被认为是数组到指针的转换,然后是限定转换 (4.4)。[示例:“abc”转换为“pointer to const char”作为数组到指针的转换,然后转换为“pointer to char”作为限定转换。]

C++11 只是删除了上面的引用,这意味着它是 C++11 中的非法代码。

在 C++03 之前,C++ 派生了不带const关键字的字符串字面量声明,请注意,这在 C 中完全有效。

于 2012-11-06T09:52:17.773 回答
4

据我了解,在 C 中,在const添加之前,这是将字符串分配给指针的方法。

在 C++ 中,这是不推荐使用的行为,但仍允许保持向后兼容性。所以不要使用它。

事实上,我相信在 C++11 中它是完全无效的。

于 2012-11-06T09:51:22.203 回答
2

不完全的。字符串文字可分配给char*类型。永远不应修改字符串文字。

这种奇怪的情况是为了向后兼容以前const存在的程序。

于 2012-11-06T09:50:29.160 回答
1

gcc -std=c++0x对此提出警告:

a.cpp:5:14:警告:不推荐将字符串常量转换为 'char*' [-Wwrite-strings]

因此,这仍然是允许的,但已被弃用,因为文字字符串是 const。

于 2012-11-06T09:54:01.750 回答
1

没有 const 类型这样的东西。const 关键字是所谓的类型限定符。它可以应用于任何指针类型,只是意味着指针指向的值不应该被修改。

您还可以通过以下方式将 const 限定符应用于指针引用本身:

char* const p ="aaa";

这将保护指针变量不指向另一个字符串。

于 2012-11-06T09:54:56.717 回答
1

有一个特殊的隐式转换来支持这一点,因为它是遗留代码中的一个常见习惯用法(通常在const存在之前编写)。你的字符串文字的类型是char const[],你应该只使用它。一个好的编译器会在上面发出警告,因为转换从引入的那一刻起就被弃用了。

请注意,这与 C 不同,其中字符串文字的类型是char[](但尝试修改它仍然是未定义的行为)。

于 2012-11-06T09:54:57.933 回答
1

您在谈论 C 字符串,它实际上是 char 的向量。在 C++ 中,std::string使用了类,并且将常量字符串创建为const std::string.

无论如何,编译器会在未来的程序中保留一块内存,以存储出现在源代码中的文字字符串。这部分内存被认为是只读的,所以你应该用const char *. 它的大小正好是字符串的大小加上尾随零的一个额外位置,标记字符串的结尾。

编译器需要保持向后兼容性,因此它们仍然接受由char *. 但是,这是一种误导,因为您不应该能够修改可以存储在嵌入式系统的 ROM 中的内存。

在我的系统中,我使用 clang:

$ clang --version
Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)
Target: i386-pc-linux-gnu
Thread model: posix

在 clang C 编译器中,这段代码编译没有错误:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char * str = "Hello, World!";

    printf( "%s", str );

    return EXIT_SUCCESS;
}

但是,相同的代码(稍作修改,例如标头的名称)在编译为 C++ 程序时会引发以下警告:

kk.cpp:6:15: warning: conversion from string literal to 'char *' is deprecated [-Wdeprecated-writable-strings]
        char * str = "Hello, World!";
                     ^
1 warning generated.

希望这可以帮助。

于 2012-11-06T10:02:18.447 回答