在我的普通C99项目中,我有一个外部C库,它定义了我需要实现的接口(通过GObject interfaces):
void interface_function (const char *address, [...]);
现在,在实现中(我需要编写)我需要从不同的库中调用一些其他函数(所以我不能更改它们),我需要传递*address
,但是他们的方法签名省略const
关键字:
void some_api_function (char *address, [...]);
现在,如果我只是将*address
传递给some_api_function
,我将收到编译器警告:
warning: passing argument 1 of ‘some_api_function’ discards ‘const’ qualifier from pointer target type [enabled by default]
我尝试在函数调用中明确地转换为char *
,如下所示:
`some_api_function ((char*) address, [...]) { ... }
然后我又得到另一个警告:
warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual]
问题是,这是一个较大的C项目,有许多人在工作,策略是-Werror
已启用,并且编译中没有代码发出警告被接受到主线源代码中。
我无法更改接口定义,因为它来自第三方,我也无法更改外部库的API定义。我知道*address
未在外部库中修改(它可能是const,但正如我所说,我无法改变它)
我也知道要解决这个问题,我可以创建const char*
到char *
的副本,但这对我来说不合适,因为它涉及不必要的复制操作。 / p>
那么优雅或“正确”的方式是什么?
答案 0 :(得分:15)
为了绝对安全,我会深入复制字符串并描述性能影响。函数的作者不保证他们不会修改字符串。如果参数标记为const char*
,则表示该函数不会更改该字符串。
还有其他选择;通过(void *)或巧妙的联合技巧(参见Gung Foo的答案),但两者都不能保证程序的稳定性。
答案 1 :(得分:7)
你可以使用联盟。
union charunion {
char *chr;
const char* cchr;
} chrptrs;
chrptrs.cchr; // const char *
chrptrs.chr; // char *
答案 2 :(得分:0)
警告是有原因的。正如Bathseheeba所说,声明并不保证函数不会修改该值,所以如果你知道你在做什么-i.e.你知道函数不会尝试修改'address'指向的值,你可以通过这样做删除警告:
void interface_function (const char *address, [...])
{
char *chrptr=(char *)address;
[...]
some_api_function (chrptr, [...]);
[...]
}
void interface_function (const char *address, [...])
{
char *chrptr=(char *)address;
[...]
some_api_function (chrptr, [...]);
[...]
}
编辑:我在回答之前回答说你要参加Bathsheeba的建议。好的选择。