在不更改API且未收到警告的情况下,将const char *转换为char *的正确方法是什么?

时间:2013-10-02 07:31:51

标签: c gcc const glib gobject

在我的普通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>

那么优雅或“正确”的方式是什么?

3 个答案:

答案 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的建议。好的选择。