【问题标题】:What would be the output of the following code snippet and why?以下代码片段的输出是什么,为什么?
【发布时间】:2020-02-14 05:25:48
【问题描述】:
#include <stdio.h>
#include <stdlib.h>
typedef    unsigned     int    U32;
int main() {
    U32 var     = -1;
    printf("var = %u\n", var);
    if(var != -1)
    {
        printf("\n I'm not -1\n");
    }
    else
    {
        printf("I'm -1 and Var :%u\n", var);
    }
 }

此处的“-1”应转换为unsigned int 并应分配给var。然后在if 条件下它不应该等于-1。但它会进入else 语句。

【问题讨论】:

  • 为什么你认为第二个-1 也不会被转换?编译器会警告您有符号/无符号比较不匹配?
  • 你也应该得到一个警告。但预计它会继续下去

标签: c implicit-conversion arithmetic-expressions


【解决方案1】:

请注意,所有整数常量,例如1,都有一个类型。鉴于U32unsigned int,那么:

  • U32 var = -1;(赋值)的情况下,int 类型的右操作数被转换为左操作数的类型。

  • if(var != -1) 的情况下,-1 操作数按照通常的算术转换从类型int 转换为unsigned int,详细信息在这里:Implicit type promotion rules

在这两种情况下,都会发生有符号到无符号的转换,并且这种转换根据 6.3.1.3 进行了明确定义:

否则,如果新类型是无符号的,则通过重复添加或转换值 比新类型可以表示的最大值多减一 直到值在新类型的范围内。

意味着在上述两种情况下,都会生成相同的无符号值0xFFFFFFFF

【讨论】:

  • 一个明确的U 后缀可能会使这更清楚并消除编译器警告。
  • @JL2210 你什么意思? -1U 只会给你不同类型的警告。
  • 它会给出什么警告?
  • @JL2210 将一元减号与无符号操作数等结合使用。
  • @JL2210 编译器不需要为此发出警告,尽管我相信有些人会这样做。静态分析器绝对可以。无论如何,毫无疑问,带有无符号操作数的一元减号是非常可疑的代码。
【解决方案2】:

在此声明中

if(var != -1)

编译器需要确定操作数的通用类型。这个过程被称为通常的算术转换。 来自 C 标准(6.5.9 等式运算符)

4 如果两个操作数都有算术类型,通常的算术 执行转换....

相对于通常的算术转换(C 标准,6.3.1.8 通常的算术转换)

否则,如果无符号整数类型的操作数有秩 大于或等于另一个操作数的类型的等级,则 带符号整数类型的操作数转换为 无符号整数类型的操作数。

所以根据 if 语句表达式中的引用,具有 int 类型的整数常量 -1 被转换为 unsigned int 类型,也就是变量 var 的类型,因为类型 int 和 unsigned int排名相同,变量var 的类型为 unsigned int。

结果条件为假。

【讨论】:

    【解决方案3】:

    一个int,无论是签名还是unsigned,都由一系列位表示,比如

    B1B2...Bn

    在哪里

    Bi ∈ {0; 1}

    现在,最大的可代表unsignedint看起来像

    1111...1
    

    但是,作为有符号值,-1 表示为

    1111...1
    

    还有

    所以,1111...1 == 1111...1 是真的。转换为unsigned 并没有改变任何值,它改变了给定值的感知方式。就记忆表示而言,2^(32-1) 和 -1 实际上是同一个家伙,穿着不同的衣服。

    【讨论】:

    • 我不确定这有多相关,因为这里重要的是如何进行整数转换。例如(long long)-1 == (unsigned long long)-1 始终为真,但(long long)-1 == (unsigned int)-1 始终为假。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-13
    相关资源
    最近更新 更多