【问题标题】:why sizeof type compared with integer returns false [duplicate]为什么 sizeof 类型与整数相比返回 false [重复]
【发布时间】:2018-09-28 05:42:00
【问题描述】:

我在下面的代码中注意到一个奇怪的行为。

#include<stdio.h>
#include <stdbool.h>

int main()
{
int x = sizeof(int) > -1;

bool z = sizeof(int);

printf("x is %d \t z is %d \n",x,z);
if(sizeof(int)>-1)
{
printf("true\n");
}
else
printf("false\n");
}

sizeof(int) > -1 为真且预期输出应为 1 时,为什么 int x 为零。

【问题讨论】:

  • 因为-1在转换为无符号类型时成为该类型可以容纳的最大值。您正在比较sizeof (int) &gt; 65535 /* or something like 2 billion */sizeof (int) &gt; -1false
  • @pmg 大概四十亿吧?
  • @unwind: 对,只失败了 1 位 :)

标签: c gcc


【解决方案1】:

GCC 编译器警告说:

prog.c: In function 'main':
prog.c:6:21: warning: comparison of integer expressions of different signedness: 'long unsigned int' and 'int' [-Wsign-compare]
 int x = sizeof(int) > -1;
                     ^
prog.c:11:15: warning: comparison of integer expressions of different signedness: 'long unsigned int' and 'int' [-Wsign-compare]
 if(sizeof(int)>-1)

因此,您正在比较 signed intunsigned long int。当-1 转换为unsigned long int 时,结果是最大可能的unsigned long int 值(与ULONG_MAX 相同)。

6.3.1.3 加元,第 2 段:

否则,如果新类型为unsigned,则值转换为 反复加或减一大于最大值 可以用新类型表示,直到值在 新类型。

欲了解更多信息,请阅读cppreference

【讨论】:

  • 我可以调试这个问题吗,任何想法,以便我可以进一步深入了解。
  • @torban 你应该在代码中避免这种情况。并注意该警告。
  • @torban 没有什么要调试的。大多数运算符将其操作数转换为匹配。对于整数unsigned 总是胜过signed。谷歌“c 中的整数转换规则”。
【解决方案2】:

sizeof 运算符产生的不是int,而是size_t,它是一个无符号整数类型。当您将像 -1 这样的有符号整数与无符号整数进行比较时,您最终会比较错误的值。

进行以下更改,代码将按预期工作。

#include<stdio.h>

#include <stdbool.h>

int main()
{
    int x = (int)sizeof(int) > -1;

    bool z = sizeof(int);

    printf("x is %d \t z is %d \n",x,z);
    if((int)sizeof(int) > -1)
    {
        printf("true\n");
    }
    else
        printf("false\n");
}

输出:

x is 1   z is 1
true

【讨论】:

    【解决方案3】:

    sizeof 运算符返回size_t 的类型

    size_t 类型是无符号类型。通常unsigned int

    如果您将unsigned int-1 进行比较,那么根据整数提升规则 (Signed to unsigned conversion in C - is it always safe?),它们都将被转换为无符号数。

    所以-1 将被转换为 65535 而等式4&gt;65535 将导致零。

    【讨论】:

      【解决方案4】:

      有符号和无符号整数类型(包括char)之间的区别在于负值由设置为 1 的最高有效位表示。在大多数平台上,在这种情况下,幅度由二进制补码表示。例如。对于char

      10000001:-(1)0000000 * 01111111 = -127

      我们应该取 00000001,从中减去 1 并将除符号之外的所有位取反得到值。

      现在,在比较有符号值时,如果其他参数是无符号的,则将其视为无符号。这有历史和实际原因,例如以避免编译遗留代码时字符比较的歧义。传统上,C 中的所有字符串都是 char* 而不是 unsigned char*。

      10000001 作为 unsigned char 等于 129。

      所以,根据这个程序,-1 大于 1。

      #include <iostream>
      
      int a = -1;
      unsigned int b = 1;
      
      int main(int argc, char** argv)
      {
          if(b < a) std::cout << "The world is mad.\n";
          if(a > b) std::cout << "Yes, it is.\n";
          return 0;
      }
      

      您始终应注意有关比较以及“可能的数据丢失”的警告。这些是程序中非常常见的错误来源。

      【讨论】:

        猜你喜欢
        • 2016-06-20
        • 2019-05-10
        • 1970-01-01
        • 2012-03-14
        • 2020-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多