关于c ++:如何摆脱GCC中从字符串常量到’char *’的过时转换警告?

关于c ++:如何摆脱GCC中从字符串常量到’char *’的过时转换警告?

How to get rid of `deprecated conversion from string constant to ‘char*’` warnings in GCC?

因此,我正在开发一个非常大的代码库,最近将其升级到gcc 4.3,现在会触发以下警告:

warning: deprecated conversion from string constant to ‘char*’

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

1
char *s ="constant string";

或类似的函数调用:

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

并使其成为const char指针。 但是,这意味着最少要触摸564个文件,这不是我目前希望执行的任务。 现在的问题是我正在使用-werror运行,因此我需要某种方式来抑制这些警告。 我怎样才能做到这一点?


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

如果您要修复某些问题,请正确修复。

说明:

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

例:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

void print(char* ch);

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

int main() {
    print("Hello");
    return 0;
}

我相信将-Wno-write-strings传递给gcc将抑制此警告。


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

对于gcc,您可以使用#pragma warning指令,如此处所述。


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

1
2
3
4
5
6
7
8
9
10
11
12
#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)。


如果它是活动的代码库,则您可能仍要升级代码库。当然,手动执行更改是不可行的,但是我相信可以通过一个sed命令彻底解决此问题。不过,我还没有尝试过,所以下面加点盐。

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

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


这是内联到文件中的方法,因此您无需修改??Makefile。

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

然后您可以...

1
#pragma GCC diagnostic pop

我不能使用编译器开关。所以我转过头了:

1
char *setf = tigetstr("setf");

对此:

1
char *setf = tigetstr((char *)"setf");

更换

1
char *str ="hello";

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

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

1
foo("hello");

替换为

1
foo((char*)"hello");

在C ++中,如下所示使用const_cast

1
char* str = const_cast<char*>("Test string");


代替:

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

这有效:

1
2
void foo(const char s[]);
foo("constant string");

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

1
char str[] ="Test string";

要么:

1
2
const char* str ="Test string";
printf(str);

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

1
(char*)"test"

从常量字符串到char指针进行类型转换,即

1
char *s = (char *)"constant string";

在C ++中,替换:

1
char *str ="hello";

有:

1
std::string str ("hello");

如果您想比较一下:

1
str.compare("HALLO");


I don't understand how to apply your solution :( – kalmanIsAGameChanger

使用Arduino Sketch,我有一个引起警告的函数。

Original function: char StrContains(char *str, char *sfind)

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

Modified: char StrContains(const char *str, const char *sfind).

所有警告都消失了。


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

例:

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

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

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

1
const char* s="constant string";

看到这种情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 ++中,它将不知道为什么。


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

例如,此代码生成警告:

1
putenv("DEBUG=1");

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

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

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

听听编译器告诉您的内容!


谢谢大家的帮助。从这里挑选到那里就是这个解决方案。这样编译干净。尚未测试代码。也许明天吧...

1
2
3
4
5
6
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数组中只有1个项目。但是可能还有更多。其余的已被注释掉以节省内存。


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


The problem right now is that I'm running with -Werror

IMO,这是您的真正问题。您可以尝试一些从(char *)转换为(const char *)的自动化方法,但是我会花钱在它们上,而不仅仅是工作。您将需要一名人员参与至少一些工作。
在短期内,只需忽略警告(但IMO保持警告状态,否则它将永远无法解决),然后删除-Werror。


将字符串声明为const将解决问题:

1
char const*s ="constant string";

BlackShift的答案非常有帮助,我使用它的方式是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
extern string execute(char* cmd) {
            FILE* pipe = popen(cmd,"r");
            if (!pipe) return"ERROR";
            char buffer[256];
            std::string result ="";
            while(!feof(pipe)) {
                    if(fgets(buffer, 128, pipe) != NULL)
                            result += buffer;
            }
            pclose(pipe);
            return result;
    }
    int main(){
            char cmd[]="grep -A1 'xml' out1.txt  | grep read|awk -F'=' 'BEGIN{sum=0}{sum=sum+$NF}END{print sum}'";
            string result=execute(cmd);
            int numOfBytes= atoi(result.c_str());  
            cout<<"Number of bytes ="<<numOfBytes<<endl;
            return 0;
    }

1
2
3
4
5
6
7
8
9
10
11
PyTypeObject PyDict_Type=
{ ...

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

监视名称字段,在gcc中会毫无警告地进行编译,但是在g ++中,它将不知道为什么。

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

g++ (Compiling C++)中的-Wwrite-strings默认情况下处于活动状态

这就是为什么会有不同的行为的原因。
对于我们来说,使用Boost_python宏会生成此类警告。
因此,在编译C ++时我们使用-Wno-write-strings,因为我们始终使用-Werror


推荐阅读