所以我正在研究一个非常大的代码库,最近升级到 gcc 4.3,现在触发了这个警告:
警告:不推荐将字符串常量转换为 'char*'
显然,解决这个问题的正确方法是找到每个声明
char *s = "constant string";
或函数调用,如:
void foo(char *s);
foo("constant string");
并使它们成为 const char
指针。但是,这意味着至少要接触 564 个文件,这不是我目前希望执行的任务。现在的问题是我正在使用 -werror
,所以我需要一些方法来抑制这些警告。我怎样才能做到这一点?
您向其中传递字符串文字 "I am a string literal"
的任何函数都应使用 char const *
而不是 char*
作为类型。
如果您要修复某些东西,请正确修复它。
解释:
您不能使用字符串文字来初始化将被修改的字符串,因为它们属于 const char*
类型。 undefined behaviour 是为了稍后修改它们而抛弃常量,因此您必须通过 char
将 const char*
字符串 char
复制到动态分配的 char*
字符串中才能修改它们。
例子:
#include <iostream>
void print(char* ch);
void print(const char* ch) {
std::cout<<ch;
}
int main() {
print("Hello");
return 0;
}
我相信将 -Wno-write-strings
传递给 gcc 会抑制此警告。
#pragma GCC diagnostic ignored "-Wwrite-strings"
。
我有一个类似的问题,我是这样解决的:
#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
)。
PyArg_ParseTupleAndKeywords
中搜索 char **
的案例,我会这样做:static char kw[][16] = {"mode", "name", "ip", "port"}; static char * kwlist[] = {kw[0], kw[1], kw[2], kw[3], NULL};
查看 gcc 的 Diagnostic Pragma 支持和 -W warning options 列表(更改:new link to warning options)。
对于 gcc,您可以使用 #pragma warning
指令,如解释的 here。
如果它是一个活动的代码库,您可能仍想升级代码库。当然,手动执行更改是不可行的,但我相信这个问题可以通过一个 sed
命令一劳永逸地解决。不过,我还没有尝试过,所以请对以下内容持保留态度。
find . -exec sed -E -i .backup -n \
-e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \;
这可能无法找到所有位置(即使不考虑函数调用),但它会缓解问题并使手动执行剩余的少数更改成为可能。
这是在文件中内联的方法,因此您不必修改 Makefile。
// gets rid of annoying "deprecated conversion from string constant blah blah" warning
#pragma GCC diagnostic ignored "-Wwrite-strings"
以后可以...
#pragma GCC diagnostic pop
我不能使用编译器开关。所以我把这个变成了:
char *setf = tigetstr("setf");
对此:
char *setf = tigetstr((char *)"setf");
代替
char *str = "hello";
和
char *str = (char*)"hello";
或者如果您正在调用函数:
foo("hello");
将其替换为
foo((char*) "hello");
代替:
void foo(char *s);
foo("constant string");
这有效:
void foo(const char s[]);
foo("constant string");
在 C++ 中,使用 const_cast
,如下所示
char* str = const_cast<char*>("Test string");
Test string
是常量字符串。所以你可以这样解决:
char str[] = "Test string";
或者:
const char* str = "Test string";
printf(str);
为什么不只使用类型转换?
(char*) "test"
strchr()
。 strchr()
函数不会更改由传入指针标识的存储,但它应该没有理由关心调用者是否会使用返回的指针来修改该存储。
做从常量字符串到字符指针的类型转换,即
char *s = (char *) "constant string";
在 C++ 中,替换:
char *str = "hello";
和:
std::string str ("hello");
如果你想比较它:
str.compare("HALLO");
我不明白如何应用您的解决方案:( – kalmanIsAGameChanger
使用 Arduino Sketch,我有一个函数会导致我的警告。
原函数:char StrContains(char *str, char *sfind)
为了停止警告,我在 char *str 和 char *sfind 前面添加了 const。
修改:char StrContains(const char *str, const char *sfind)。
所有警告都消失了。
看到这种情况:
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()
从字符串常量创建可写字符串。
例如,此代码会生成警告:
putenv("DEBUG=1");
但是,以下代码不会(在将字符串传递给 putenv
之前,它会在堆上复制字符串):
putenv(strdup("DEBUG=1"));
在这种情况下(也许在大多数其他情况下)关闭警告是一个坏主意——它的存在是有原因的。另一种选择(默认情况下使所有字符串可写)可能效率低下。
听听编译器告诉你什么!
putenv()
的特殊情况令人担忧——它不是一个好的示例选择(至少,对于 putenv()
所做的事情的讨论比这个答案中的更多)。这是一个完全独立的讨论。 (请注意,基于定义 POSIX 之前的遗留实现,针对 putenv()
行为的 POSIX 规范是有问题的。)IIRC,在最近(本千年)发布的 GNU C 库中存在一个与putenv()
行为改变,并被改回。)
只需对 g++ 使用 -w 选项
例子:
g++ -w -o simple.o simple.cpp -lpthread
请记住,这并不能避免弃用,而是会阻止在终端上显示警告消息。
现在,如果您真的想避免弃用,请使用 const 关键字,如下所示:
const char* s="constant string";
为什么不使用 -Wno-deprecated
选项来忽略已弃用的警告消息?
谢谢大家的帮助。从这里和那里挑选这个解决方案。这编译干净。还没有测试代码。也许明天吧...
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 数组中只有一项。但可能还有更多。其余的暂时被注释掉以节省内存。
将 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]
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
现在的问题是我正在运行 -Werror
这是你真正的问题,IMO。您可以尝试一些从 (char *) 移动到 (const char *) 的自动化方法,但我会为它们投入资金,而不仅仅是工作。您必须至少有人参与其中的一些工作。在短期内,只需忽略警告(但 IMO 将其保持打开状态,否则将永远无法修复)并删除 -Werror。
不定期副业成功案例分享
char *
/const char *
的 3rd 方 API,因此在这种情况下,我通常会进行转换。char*
,即使对于不会被修改的字符串也是如此。如果您将参数作为char const*
并将其传递给采用char*
的标准函数,您将成功。如果库函数不会处理字符串,您可以丢弃const
。