如何修复警告:"签名和未签名之间的比较"?

Geo*_*rge 14 c

我被建议在GCC中使用以下选项,因为它有助于避免许多常见错误.它会打开一堆警告并将-Werror其变成错误.

gcc -pedantic -W -Wall -Wextra -Wshadow -Wstrict-overflow=5 -Wwrite-strings -std=c99 -Werror
Run Code Online (Sandbox Code Playgroud)

鉴于以下测试代码:

#include <stdio.h>

int main(void)
{
    int arr[8]={0,10,20,30,40,50,60,70};
    int x;

    printf("sizeof(arr): %d\n", sizeof(arr));
    printf("sizeof(int): %d\n", sizeof(int));

    for(x = 0; x < sizeof(arr)/sizeof(int); x++)
    {
        printf("%d\n",arr[x]);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我明白了:

test.c:11: error: comparison between signed and unsigned
Run Code Online (Sandbox Code Playgroud)

我知道我能解决这个问题的一种方法就是关闭警告,但是他们还没有让我使用这些设置来最终关闭它们.

另一种方法是投射东西,但我被告知铸造已被弃用.

另外,我可以将x变为unsigned int:

unsigned x;
Run Code Online (Sandbox Code Playgroud)

但是,当我必须使用这些编译器选项将带符号值与无符号值进行比较时,它无法解决一般问题.是否有更清洁的方式而不是铸造?

dir*_*tly 15

更换

int x;
/* ... */
for(x=0;x<sizeof(arr) / sizeof(int);x++)
Run Code Online (Sandbox Code Playgroud)

通过

for(size_t x=0;x<sizeof(arr) / sizeof(int);x++)
Run Code Online (Sandbox Code Playgroud)

但是,当我必须使用这些编译器选项将带符号值与无符号值进行比较时,它无法解决一般问题.是否有更清洁的方式铸造?

在这种情况下,请尝试确定带符号的数字是否会有一个会导致溢出的值.如果没有,您可以忽略该警告.否则,对无符号类型的强制转换(如果它与签名组件大小相同或更大)就足够了.

  • 我同意这个答案.另请注意,不会弃用转换,但对于初学者来说可能不鼓励,因为它可能会导致一些不良习惯. (3认同)

Jar*_*Par 5

这实际上取决于数据类型。通过将值隐式转换为包含有符号和无符号类型中所有可用值的超集的类型,可以避免这种情况。例如,您可以使用64位带符号的值来比较无符号的32位和带符号的32位值。

但是,这是一个极端的情况,您需要执行一些操作,例如验证类型的大小。最好的解决方案是对两个操作数使用相同的类型。

如果必须强制转换,请务必考虑可能导致溢出,并考虑这是否对您的应用程序很重要。