C89:签名/未签名不匹配

时间:2010-02-14 20:56:26

标签: size c89

签名/未签名的不匹配是否一定不好?

这是我的计划:

int main(int argc, char *argv[]) {
    unsigned int i;

    for (i = 1; i < argc; i++) { // signed/unsigned mismatch here

    }
}

argc已签名,i未签署。这是一个问题吗?

4 个答案:

答案 0 :(得分:9)

“签名/未签名的不匹配”可能不好。在你的问题中,你问的是比较。比较相同基本类型的两个值,但是一个有符号值和一个无符号值时,有符号值将转换为无符号值。所以,

int i = -1;
unsigned int j = 10;

if (i < j)
    printf("1\n");
else
    printf("2\n");

打印2而不是1.这是因为在i < j中,i转换为unsigned int(unsigned int)-1等于UINT_MAX,这是一个非常大的数字。因此,条件的计算结果为false,您将进入else子句。

对于您的特定示例,argc保证是非负面的,因此您不必担心“不匹配”。

答案 1 :(得分:1)

在您的特定情况下,这不是一个真正的问题,但编译器无法知道argc将始终具有不会导致任何问题的值。

答案 2 :(得分:1)

这只是间接的问题。

如果您使用有符号运算(例如&|<<>>),可能会发生错误。
如果使用无符号整数进行算术运算,则会发生完全不同的不良事件(如果数字为>= 0等,则在测试时出现下溢,无限循环等。)

因此,当您在任一类型的操作(算术或位操作)中混合有符号和无符号整数时,某些编译器和静态检查工具将发出警告。

虽然在例如您的示例的简单情况下混合它们是安全的,但如果您这样做,则意味着您无法使用这些静态检查工具(或必须禁用这些警告),这可能意味着其他错误未被检测到。

有时你别无选择,例如在内存管理代码中对类型size_t的值进行算术运算时。

在你的例子中,我会坚持int,因为它有更少的类型更简单,并且int无论如何都会在那里,因为它是第一个参数的类型main()

答案 3 :(得分:1)

还不错。我会修复有关签名/无符号不匹配的编译器警告,因为即使不可能或不可能,也会发生坏事。当你因为签名/无符号不匹配而必须修复错误时,编译器基本上会说“我告诉过你”。不要忽视它的警告。