如何摆脱GCC中从字符串常量到'char *''警告的弃用转换?

时间:2008-09-12 18:15:55

标签: c++ string gcc

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

  

警告:已弃用从字符串常量转换为'char *'

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

char *s = "constant string";

或函数调用如:

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

并使它们const char指针。但是,这意味着触及564个文件,最小,这不是我希望在此时执行的任务。现在的问题是我正在运行-werror,所以我需要一些方法来扼杀这些警告。我怎么能这样做?

25 个答案:

答案 0 :(得分:545)

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

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

<强>解释

您不能使用字符串文字初始化将要修改的字符串,因为它们的类型为const char*。转换constness以便稍后修改它们是undefined behaviour,因此您必须将const char*字符串char复制char到动态分配的char*字符串中,以便修改它们。

示例:

#include <iostream>

void print(char* ch);

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

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

答案 1 :(得分:217)

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

答案 2 :(得分:69)

查看gcc的Diagnostic Pragma支持以及-W warning options列表(已更改:new link to warning options)。

对于gcc,您可以使用#pragma warning指令,如解释here

答案 3 :(得分:68)

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

#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)。

答案 4 :(得分:29)

如果它是活动代码库,您可能仍希望升级代码库。当然,手动执行更改是不可行的,但我相信这个问题可以通过一个sed命令一劳永逸地解决。但是,我没有尝试过,所以请注意以下几点。

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

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

答案 5 :(得分:25)

替换

char *str = "hello";

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

或者如果你正在打电话:

foo("hello");

替换它
foo((char*) "hello");

答案 6 :(得分:25)

我无法使用编译器开关。所以我转过身来了:

char *setf = tigetstr("setf");

到此:

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

答案 7 :(得分:25)

以下是如何在文件中内联,因此您不必修改Makefile。

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

你可以稍后......

#pragma GCC diagnostic pop

答案 8 :(得分:15)

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

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

答案 9 :(得分:15)

而不是:

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

这有效:

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

答案 10 :(得分:7)

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

char str[] = "Test string";

或:

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

答案 11 :(得分:5)

为什么不使用类型转换?

(char*) "test"

答案 12 :(得分:3)

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

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

答案 13 :(得分:1)

看到这种情况:

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 ++中它会,我不知道为什么。

答案 14 :(得分:1)

在C ++中,替换:

char *str = "hello";

使用:

std::string str ("hello");

如果你想比较它:

str.compare("HALLO");

答案 15 :(得分:1)

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

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

putenv("DEBUG=1");

但是,以下代码没有(它在将字符串传递给putenv之前在堆上创建了一个字符串的副本):

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

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

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

答案 16 :(得分:1)

  

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

使用Arduino Sketch,我有一个功能导致我的警告。

  
    

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

  

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

  
    

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

  

所有警告都消失了。

答案 17 :(得分: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数组中只有1个项目。但可能会有更多。其余的人现在被评论出来以节省记忆。

答案 18 :(得分: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]

答案 19 :(得分:0)

BlackShift的回答非常有用,我用过它:

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;
    }

答案 20 :(得分:0)

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

示例:

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

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

现在,如果你真的想避免弃用,请使用这样的const关键字:

const char* s="constant string";  

答案 21 :(得分:0)

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

答案 22 :(得分:0)

  

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

这是你真正的问题,IMO。您可以尝试一些从(char *)转移到(const char *)的自动方式,但我会把钱放在它们上面而不仅仅是工作。你必须让一个人参与至少一些工作。 在短期内,只需忽略警告(但IMO将其保留,或者它永远不会被修复),只需删除-Werror。

答案 23 :(得分:-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处于活动状态。

g++ (Compiling C++)中的

-Wwrite-strings默认处于活动状态

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

答案 24 :(得分:-1)

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

char const*s = "constant string";