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

Jos*_*ews 401 c++ string gcc

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

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

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

char *s = "constant string";
Run Code Online (Sandbox Code Playgroud)

或函数调用如:

void foo(char *s);
foo("constant string");
Run Code Online (Sandbox Code Playgroud)

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

Joh*_*ohn 558

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

如果你要解决问题,请正确解决问题.

说明:

您不能使用字符串文字初始化将要修改的字符串,因为它们是类型const char*.虚掷常量性以后修改它们是不确定的行为,所以你要复制你的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;
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然这是真的,但你并不总能控制第三方API,它们可能无法正确使用`char*`/`const char*`,所以在这种情况下我通常会施放. (25认同)
  • @ppumkin不幸的是,许多C标准库字符串函数将参数作为`char*`,即使对于不会被修改的字符串也是如此.如果你把一个参数作为`char const*'并将它传递给一个带有`char*`的标准函数,那你就可以点击它.如果库函数不会操作字符串,你可以抛弃`const`. (14认同)

DGe*_*try 222

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

  • 这是令人难以置信的糟糕做法,我很遗憾它得到了所有这些选票.没有警告,所以你忽略它们.警告告诉你"伙计,你做的事情可能是错的,要小心",你应该只在你想回应时压抑它们,比如"闭嘴,我知道我在做什么",这很可能不是婴儿程序员的情况. (210认同)
  • @PriyankBolia bdonlan评论了Rob Walker的答案,它可以使用`#pragma GCC diagnostic ignored"-Wwrite-strings"`. (18认同)
  • 除非您控制API,在这种情况下@ John的答案,关于更改签名以接受const char*,更为正确. (9认同)
  • 我同意,你不应该摆脱警告,而是使用约翰提供的解决方案.太糟糕了这个是接受的答案! (9认同)
  • 是否可以使用pragma在每个文件基础上禁用它. (6认同)
  • 警告的问题在于,真正重要的警告很容易在小警告、构建进度报告等的海洋中迷失。而错误会立即引起注意,因为它们会导致构建失败。在开发过程中,IMO 最好使用“-Wno-error=”使个别警告成为非致命的,而不是完全摆脱 Werror。 (2认同)

Rob*_*ker 69

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

对于gcc,您可以使用此处#pragma warning说明的指令.

  • 实际上它确实:#pragma GCC诊断忽略了"-Wwrite-strings" (54认同)

Bla*_*ift 69

我遇到了类似的问题,我解决了这个问题:

#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);
}
Run Code Online (Sandbox Code Playgroud)

这是解决这个问题的合适方法吗?我没有权限foo让它接受const char*,虽然这将是一个更好的解决方案(因为foo不会改变m).

  • @elcuco,你会建议什么?我无法编辑foo,并试图找到一个不需要抑制警告的解决方案.就我而言,后者更多的是运动问题,但对于原始海报来说,它似乎很重要.据我所知,我的答案是唯一能够同时解决我和OP条件的答案,因此它可能是对某人有价值的答案.如果您认为我的解决方案不够好,请您提供替代方案吗?(这不包括编辑foo或忽略警告.) (8认同)
  • 虽然这种方法在某些情况下可能有优点,但盲目应用它可能弊大于利。盲目应用这一点很容易导致悬空指针。它还会使代码因无意义的字符串副本而膨胀。 (2认同)

Kon*_*lph 30

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

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

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

  • 这只能解决声明警告而不是函数调用+1 for sed fu:p (7认同)

vy3*_*y32 25

我不能使用编译器开关.所以我转过身来:

char *setf = tigetstr("setf");
Run Code Online (Sandbox Code Playgroud)

对此:

char *setf = tigetstr((char *)"setf");
Run Code Online (Sandbox Code Playgroud)

  • 真正烦人的是 tigetstr() 应该用 (const char *) 原型化,而不是 (char *) (2认同)
  • 当我这样做时,我得到"警告:从类型'const char*'强制转换为'char*'强制转换为constness".我不得不使用const_cast来消除所有警告:const_cast <char*>("setf") (2认同)
  • 我认为const cast是此页面上第一个可接受的解决方案(API更改除外). (2认同)

EdH*_*EdH 25

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

// gets rid of annoying "deprecated conversion from string constant blah blah" warning
#pragma GCC diagnostic ignored "-Wwrite-strings"
Run Code Online (Sandbox Code Playgroud)

你可以稍后......

#pragma GCC diagnostic pop
Run Code Online (Sandbox Code Playgroud)


小智 25

更换

char *str = "hello";
Run Code Online (Sandbox Code Playgroud)

char *str = (char*)"hello";
Run Code Online (Sandbox Code Playgroud)

或者如果你在函数中调用:

foo("hello");
Run Code Online (Sandbox Code Playgroud)

用它代替

foo((char*) "hello");
Run Code Online (Sandbox Code Playgroud)


小智 15

代替:

void foo(char *s);
foo("constant string");
Run Code Online (Sandbox Code Playgroud)

这有效:

void foo(const char s[]);
foo("constant string");
Run Code Online (Sandbox Code Playgroud)


app*_*apu 15

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

char* str = const_cast<char*>("Test string");
Run Code Online (Sandbox Code Playgroud)


小智 7

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

char str[] = "Test string";
Run Code Online (Sandbox Code Playgroud)

要么:

const char* str = "Test string";
printf(str);
Run Code Online (Sandbox Code Playgroud)