我该如何避免gcc警告,针对普通的“char”到“unsigned char”或“signed char”的转换?

3
我的默认字符类型是“无符号字符”(在gcc选项中设置为-funsigned-char gcc)。因此,可以说当我需要“无符号字符”时,可以使用“char”在代码中。但是,当我在(char*)和(unsigned char*或signed char*)之间进行转换时,会收到警告:
“error: pointer targets in passing argument 1 of 'test2' differ in signedness”。
在我的系统中,编译器选项将默认的字符设为无符号字符,我如何在将unsigned char*变量传递给char*时避免警告呢?
static void test2(char* a)      //char is unsigned by deafult as set by -funsigned-char gcc option
{
}

void    test1(void)
{
        // This passes, but if i change it to unsigned char (or 'signed char') it fails   
        // I dont want it to fail for "unsigned char c" since default char is unsigned.
        char    c = 65; 
        test2(&c);
}

错过了一个要点,源代码中我不需要进行强制类型转换,因为我必须在许多地方编辑庞大的代码库。 - Lunar Mushrooms
您提供的示例代码在使用gcc (Debian 4.4.5-8) 4.4.5编译时,无论是否使用-funsigned-char选项,均不会出现警告。 - alk
1
是的,它可以使用旧版本编译器进行编译,但当我使用新版本gcc编译器时,unsigned char c = 65将在test2(&c)处出现错误。 - Lunar Mushrooms
2
开关使char无符号,但它并不是unsigned char!类型charsigned charunsigned char仍然是不同的类型。 - Bo Persson
“它能够编译通过旧的编译器版本”这个评论是关键。虽然在2000年左右这种方式曾经有效,但从那时起,由于某些原因(可能是标准遵从性),gcc开发人员使其比以前更加严格。 - Per Lundberg
4个回答

7
开关-funsigned-char-fsigned-char并不是指char *
你可以使用-Wno-pointer-sign来关闭你收到的警告。

3
正确的解决方法是将正确类型的变量传递给函数。例如,如果函数需要一个普通字符,则应声明一个普通字符并获取其地址,以此类推。
C标准规定,“char”,“signed char”和“unsigned char”是不同的类型。“char”的行为必须与“signed char”或“unsigned char”中的一个相同,由编译器开关确定,但不能互换使用。您应该编写无论是否使用-funsigned-char都能完全相同工作的代码。
另一位用户建议使用强制转换不是好主意。这只是抑制了警告,更清楚的方法是显式禁用警告(例如使用pragma),或在makefile中全局关闭警告。
强制转换没有解决代码问题,只是停止编译器指出问题。这是一个略微学术的观点,但在非2的补码系统上,有符号字符可能有陷阱表示(它们对于值0 <= x <= CHAR_MAX具有布局兼容性,但不适用于其他值)。所以代码可能会崩溃。
根据您提供的细节,在实际情况下,最好的解决方案可能就是禁用警告,并接受代码在这方面不可移植的事实。

3

使用强制类型转换:

char c = 65;   // weird magic :-(

test2((unsigned char *)(&c));

所有字符类型都是布局兼容的,将它们的指针转换不构成类型游戏或违反别名规则,因此您可以自由地这样做。

我不需要在源代码中进行强制转换,因为我必须在许多地方编辑一个巨大的代码库(我的代码可以使用旧编译器编译,但新版本开始给我警告)。 - Lunar Mushrooms

1

终于我得到了答案:

-Wpointer-sign 被 -Wall 和 -pedantic 隐含。为避免警告,请使用 -Wno-pointer-sign。


这会禁用将 int * 传递给 unsigned * 的警告吗? - jxh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接