423

所以我正在研究一个非常大的代码库,最近升级到 gcc 4.3,现在触发了这个警告:

警告:不推荐将字符串常量转换为 'char*'</p>

显然,解决这个问题的正确方法是找到每个声明

char *s = "constant string";

或函数调用,如:

void foo(char *s);
foo("constant string");

并使他们成为const char指针。但是,这意味着至少要接触 564 个文件,这不是我目前希望执行的任务。现在的问题是我正在运行-werror,所以我需要一些方法来扼杀这些警告。我怎样才能做到这一点?

4

23 回答 23

577

将字符串文字传递给的任何函数"I am a string literal"都应用char const *作类型,而不是char*.

如果您要修复某些东西,请正确修复它。

解释:

您不能使用字符串文字来初始化将被修改的字符串,因为它们是const char*. 抛弃常量以稍后修改它们是未定义的行为,因此您必须将const char*字符串复制charchar动态分配char*的字符串中才能修改它们。

例子:

#include <iostream>

void print(char* ch);

void print(const char* ch) {
    std::cout<<ch;
}

int main() {
    print("Hello");
    return 0;
}
于 2013-05-31T23:07:31.847 回答
238

我相信传递-Wno-write-strings给 gcc 会抑制这个警告。

于 2008-09-12T18:22:10.030 回答
73

我有一个类似的问题,我是这样解决的:

#include <string.h>

extern void foo(char* m);

int main() {
    // warning: deprecated conversion from string constant to ‘char*’
    //foo("Hello");

    // no more warning
    char msg[] = "Hello";
    foo(msg);
}

这是解决这个问题的合适方法吗?我无法将foo其调整为接受const char*,尽管这将是一个更好的解决方案(因为foo不会改变m)。

于 2009-02-12T12:44:01.997 回答
68

查看 gcc 的Diagnostic Pragma支持,以及-W 警告选项列表(更改:警告选项的新链接)。

对于 gcc,您可以使用此处#pragma warning解释的指令。

于 2008-09-12T18:23:43.600 回答
33

如果它是一个活动的代码库,您可能仍想升级代码库。sed当然,手动执行更改是不可行的,但我相信这个问题可以通过一个命令一劳永逸地解决。不过,我还没有尝试过,所以请对以下内容持保留态度。

find . -exec sed -E -i .backup -n \
    -e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \;

这可能无法找到所有位置(甚至不考虑函数调用),但它会缓解问题并可以手动执行剩余的少数更改。

于 2008-09-12T18:49:22.133 回答
27

这是在文件中内联的方法,因此您不必修改 Makefile。

// gets rid of annoying "deprecated conversion from string constant blah blah" warning
#pragma GCC diagnostic ignored "-Wwrite-strings"

以后可以...

#pragma GCC diagnostic pop
于 2011-11-15T17:47:40.553 回答
25

我不能使用编译器开关。所以我把这个变成了:

char *setf = tigetstr("setf");

对此:

char *setf = tigetstr((char *)"setf");
于 2009-08-21T02:14:26.480 回答
25

代替

char *str = "hello";

char *str = (char*)"hello";

或者如果您正在调用函数:

foo("hello");

将其替换为

foo((char*) "hello");
于 2015-10-09T19:52:09.817 回答
15

代替:

void foo(char *s);
foo("constant string");

这有效:

void foo(const char s[]);
foo("constant string");
于 2014-10-04T15:06:56.410 回答
14

在 C++ 中,使用const_cast如下

char* str = const_cast<char*>("Test string");
于 2015-05-15T08:37:33.987 回答
7

Test string是常量字符串。所以你可以这样解决:

char str[] = "Test string";

或者:

const char* str = "Test string";
printf(str);
于 2010-03-17T10:18:26.257 回答
3

为什么不只使用类型转换?

(char*) "test"
于 2010-12-21T15:14:35.997 回答
2

做从常量字符串到字符指针的类型转换,即

char *s = (char *) "constant string";
于 2014-07-15T12:36:13.200 回答
1

在 C++ 中,替换:

char *str = "hello";

和:

std::string str ("hello");

如果你想比较它:

str.compare("HALLO");
于 2017-12-21T12:56:22.297 回答
1

我不明白如何应用您的解决方案:( – kalmanIsAGameChanger

使用 Arduino Sketch,我有一个函数会导致我的警告。

原函数:char StrContains(char *str, char *sfind)

为了停止警告,我在 char *str 和 char *sfind 前面添加了const 。

修改:char StrContains(const char *str, const char *sfind)。

所有警告都消失了。

于 2018-03-08T20:03:34.157 回答
0

为什么不使用-Wno-deprecated忽略已弃用警告消息的选项?

于 2008-10-26T05:53:56.303 回答
0

您还可以通过调用从字符串常量创建可写字符串strdup()

例如,此代码会生成警告:

putenv("DEBUG=1");

但是,以下代码不会(它在将字符串传递给之前在堆上复制字符串putenv):

putenv(strdup("DEBUG=1"));

在这种情况下(也许在大多数其他情况下)关闭警告是一个坏主意——它的存在是有原因的。另一种选择(默认情况下使所有字符串可写)可能效率低下。

听听编译器告诉你什么!

于 2009-05-05T20:49:48.093 回答
0

看到这种情况:

typedef struct tagPyTypeObject
{
    PyObject_HEAD;
    char *name;
    PrintFun print;
    AddFun add;
    HashFun hash;
} PyTypeObject;

PyTypeObject PyDict_Type=
{
    PyObject_HEAD_INIT(&PyType_Type),
    "dict",
    dict_print,
    0,
    0
};

观察名称字段,在 gcc 中它编译时没有警告,但在 g++ 中它会,我不知道为什么。

于 2010-08-24T02:14:08.547 回答
0

只需对 g++ 使用 -w 选项

例子:

g++ -w -o simple.o simple.cpp -lpthread

请记住,这并不能避免弃用,而是会阻止在终端上显示警告消息。

现在,如果您真的想避免弃用,请使用 const 关键字,如下所示:

const char* s="constant string";  
于 2012-06-08T16:43:11.687 回答
0

谢谢大家的帮助。从这里和那里挑选这个解决方案。这编译干净。还没有测试代码。也许明天吧...

const char * timeServer[] = { "pool.ntp.org" }; // 0 - Worldwide 
#define WHICH_NTP            0 // Which NTP server name to use.
...
sendNTPpacket(const_cast<char*>(timeServer[WHICH_NTP])); // send an NTP packet to a server
...
void sendNTPpacket(char* address) { code }

我知道,timeServer 数组中只有一项。但可能还有更多。其余的暂时被注释掉以节省内存。

于 2016-03-05T11:47:49.743 回答
0

在传递string constants给函数时,将其写为:

void setpart(const char name[]);

setpart("Hello");

而不是const char name[],你也可以写const char \*name

它对我来说消除了这个错误:

[Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings]
于 2020-09-13T06:13:49.237 回答
-1

现在的问题是我正在运行 -Werror

这是你真正的问题,IMO。您可以尝试一些从 (char *) 移动到 (const char *) 的自动化方法,但我会为它们投入资金,而不仅仅是工作。您必须至少有人参与其中的一些工作。在短期内,只需忽略警告(但 IMO 将其保持打开状态,否则将永远无法修复)并删除 -Werror。

于 2008-09-15T22:33:15.813 回答
-1
PyTypeObject PyDict_Type=
{ ...

PyTypeObject PyDict_Type=
{
  PyObject_HEAD_INIT(&PyType_Type),
                     "dict",
                     dict_print,
                     0,
                     0
}; 

观察名称字段,在 gcc 中它编译时没有警告,但在 g++ 中它会,我不知道为什么。

gcc (Compiling C), -Wno-write-strings 默认情况下是活动的。

in g++ (Compiling C++)-Wwrite-strings 默认激活

这就是为什么会有不同的行为。对于我们使用宏会Boost_python产生这样的警告。所以我们-Wno-write-strings在编译 C++ 时使用,因为我们总是使用-Werror

于 2012-05-14T13:55:13.170 回答