169

我有一堂课private char str[256];

为此我有一个显式的构造函数:

explicit myClass(const char *func)
{
    strcpy(str,func);
}

我称之为:

myClass obj("example");

当我编译它时,我收到以下警告:

不推荐将字符串常量转换为 'char*'

为什么会这样?

4

11 回答 11

164

这是您在遇到如下情况时看到的错误消息:

char* pointer_to_nonconst = "string literal";

为什么?好吧,C 和 C++ 在字符串文字的类型上有所不同。在 C 中,类型是 char 数组,而在 C++ 中,类型是 char常量数组。在任何情况下,您都不允许更改字符串文字的字符,因此 C++ 中的 const 并不是真正的限制,而是更多的类型安全。出于安全原因,如果没有明确的强制转换,从const char*to的转换char*通常是不可能的。但是为了与 C 向后兼容,C++ 语言仍然允许将字符串文字分配给 achar*并警告您不推荐使用此转换。

因此,为了 const 的正确性,您在程序中缺少一个或多个consts。但是您向我们展示的代码不是问题,因为它没有进行这种已弃用的转换。警告一定来自其他地方。

于 2009-10-06T09:23:07.397 回答
150

警告:

不推荐将字符串常量转换为 'char*'

给出是因为您正在某处(而不是在您发布的代码中)执行以下操作:

void foo(char* str);
foo("hello");

问题是您正在尝试将字符串文字(类型为const char[])转换为char*.

您可以将 a 转换为const char[]const char*因为数组衰减到指针,但是您正在做的是使可变的常量。

这种转换可能是为了 C 兼容性而允许的,只是给你提到的警告。

于 2009-10-07T13:32:35.130 回答
106

作为答案没有。2 fnieto - Fernando Nieto清楚而正确地描述了发出此警告是因为您正在执行的代码中的某处(而不是您发布的代码中)类似于:

void foo(char* str);
foo("hello");

但是,如果您还想保持代码无警告,那么只需对代码进行相应的更改:

void foo(char* str);
foo((char *)"hello");

也就是说,只需将string常量转换为(char *)

于 2010-12-21T17:18:53.153 回答
48

有3个解决方案:

解决方案1:

const char *x = "foo bar";

解决方案2:

char *x = (char *)"foo bar";

解决方案3:

char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");

数组也可以用来代替指针,因为数组已经是一个常量指针。

于 2014-07-10T13:04:43.740 回答
5

这个问题的一个原因(这比char* str = "some string"其他人解释的问题更难检测)是当您使用constexpr.

constexpr char* str = "some string";

似乎它的行为类似于const char* str,因此不会像之前那样引起警告,char*而是表现为char* const str

细节

常量指针,以及指向常量的指针。const char* str和之间的区别char* const str可以解释如下。

  1. const char* str: 将 str 声明为指向 const char 的指针。这意味着这个指针指向的数据是不变的。可以修改指针,但任何修改数据的尝试都会引发编译错误。
    1. str++ ;:有效。我们正在修改指针,而不是指向的数据。
    2. *str = 'a';:无效。我们正在尝试修改指向的数据。
  2. char* const str: 将 str 声明为指向 char 的 const 指针。这意味着该点现在是恒定的,但指向的数据也不是。指针无法修改,但我们可以使用指针修改数据。
    1. str++ ;:无效。我们正在尝试修改指针变量,它是一个常量。
    2. *str = 'a';:有效。我们正在尝试修改指向的数据。在我们的例子中,这不会导致编译错误,但会导致运行时错误,因为字符串很可能会进入已编译二进制文件的只读部分。如果我们动态分配了内存,这个语句就有意义了,例如。char* const str = new char[5];.
  3. const char* const str: 将 str 声明为指向 const char 的 const 指针。在这种情况下,我们既不能修改指针,也不能修改指向的数据。
    1. str++ ;:无效。我们正在尝试修改指针变量,它是一个常量。
    2. *str = 'a';:无效。我们试图修改这个指针指向的数据,它也是常量。

就我而言,问题是我希望constexpr char* str表现得像const char* str,而不是char* const str,因为在视觉上它似乎更接近前者。

此外,生成的警告constexpr char* str = "some string"char* str = "some string".

  1. 编译器警告constexpr char* str = "some string"ISO C++11 does not allow conversion from string literal to 'char *const'
  2. 编译器警告char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *'

提示

您可以使用C gibberish ↔ 英语转换器C声明转换为易于理解的英语语句,反之亦然。这是C唯一的工具,因此不支持C++.

于 2019-09-08T08:41:29.753 回答
4

事实上,字符串常量文字既不是 const char * 也不是 char*,而是 char[]。它很奇怪,但写在 c++ 规范中;如果您修改它,则行为未定义,因为编译器可能会将其存储在代码段中。

于 2009-10-06T08:59:35.570 回答
4

也许你可以试试这个:

void foo(const char* str) 
{
    // Do something
}

foo("Hello")

这个对我有用

于 2018-11-20T06:37:54.857 回答
1

我通过在代码开头的某个地方添加这个宏来解决这个问题。或者加进去<iostream>,呵呵。

 #define C_TEXT( text ) ((char*)std::string( text ).c_str())
于 2011-09-15T06:59:23.870 回答
0

我也遇到了同样的问题。而我所做的只是添加 const char* 而不是 char*。问题解决了。正如其他人在上面提到的那样,这是一个兼容错误。C 将字符串视为 char 数组,而 C++ 将它们视为 const char 数组。

于 2015-10-12T15:19:06.110 回答
0

对于它的价值,我发现这个简单的包装类有助于将 C++ 字符串转换为char *

class StringWrapper {
    std::vector<char> vec;
public:
    StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
    }

    char *getChars() {
        return &vec[0];
    }
};
于 2018-02-26T13:30:20.600 回答
-1

下面说明了解决方案,将您的字符串分配给指向 char 常量数组的变量指针(字符串是指向 char 常量数组的常量指针 - 加上长度信息):

#include <iostream>

void Swap(const char * & left, const char * & right) {
    const char *const temp = left;
    left = right;
    right = temp;
}

int main() {
    const char * x = "Hello"; // These works because you are making a variable
    const char * y = "World"; // pointer to a constant string
    std::cout << "x = " << x << ", y = " << y << '\n';
    Swap(x, y);
    std::cout << "x = " << x << ", y = " << y << '\n';
}
于 2011-09-16T00:39:30.307 回答