8

在我的普通 C99 项目中,我有一个外部 C 库,它定义了一个我需要实现的接口(通过GObject 接口):

void interface_function (const char *address, [...]);

现在,在实现(我需要编写)中,我需要从需要传递的不同库中调用其他一些函数(所以我不能更改它们)*address,但是它们的方法签名省略了const关键字:

void some_api_function (char *address, [...]);

现在,如果我简单地传递*addresssome_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*into的副本char *,但这对我来说感觉不对,因为它涉及不必要的复制操作。

那么这样做的优雅或“正确”方法是什么?

4

3 回答 3

16

为了绝对安全,我会深度复制字符串并分析性能影响。该函数的作者不保证他们不会修改字符串。如果参数被标记const char*,则意味着该字符串不会被函数更改。

还有其他选择;通过 (void*) 或巧妙的联合技巧进行转换(参见 Gung Foo 的回答),但两者都不能保证程序的稳定性。

于 2013-10-02T07:35:54.557 回答
8

你可以使用工会。

union charunion {
   char *chr;
   const char* cchr;
} chrptrs;

chrptrs.cchr; // const char *
chrptrs.chr;  // char *
于 2013-10-02T07:36:06.733 回答
0

警告是有原因的。正如 Bathseheeba 所说,声明不能保证函数不会修改值,所以如果你知道你在做什么——即你知道函数不会尝试修改“地址”指向的值——你可以删除通过这样做警告:

void interface_function (const char *address, [...])
{
    char *chrptr=(char *)address;
    [...]
    some_api_function (chrptr, [...]);
    [...]
 }

编辑:在您评论您将接受 Bathsheeba 的建议之前,我正在回答。好的选择。

于 2013-10-02T09:12:50.073 回答