代码之家  ›  专栏  ›  技术社区  ›  Ash

两字节变量上的c xor在没有强制转换的情况下无法编译[重复]

  •  27
  • Ash  · 技术社区  · 14 年前

    这个问题已经有了答案:

    下面为什么会引发编译时错误:“无法将类型“int”隐式转换为“byte”:

            byte a = 25;
            byte b = 60;
    
            byte c = a ^ b;
    

    如果我使用算术运算符,这是有意义的,因为A+B的结果可能比存储在单个字节中的结果大。

    然而,将此应用于XOR运算符是毫无意义的。这里是一个永远不会溢出字节的位操作。

    使用围绕两个操作数的强制转换可以:

    byte c = (byte)(a ^ b);
    
    8 回复  |  直到 8 年前
        1
  •  23
  •   Michael Burr    14 年前

    我不能给你理由,但我可以从编译器必须遵循的规则(这可能不是你真正感兴趣的知识)的角度来解释为什么编译器有这种行为。

    从C规范的旧版本(我可能会下载一个更新的版本)中,Emphasis补充道:

    14.2.6.2二进制数字促销-本条款提供信息。

    二进制数字升级发生在 预定义的操作数 + , ? , * , / , % , & , | , ^ , == , != , > , < , >= <= 二元运算符。二元的 数值提升隐式转换 两个操作数都是一个公共类型, 在非关系的情况下 运算符,也将成为结果 操作的类型。二进制数值 提升包括应用 遵循规则,按顺序 出现在这里:

    • 如果其中一个操作数是十进制类型,则另一个操作数是 转换为十进制类型,或 如果另一个 操作数的类型为float或double。
    • 否则,如果其中一个操作数是double类型,则另一个操作数是 已转换为Double类型。
    • 否则,如果其中一个操作数是float类型,则另一个操作数是 已转换为float类型。
    • 否则,如果其中一个操作数是ulong类型,则另一个操作数是 转换为ulong类型,或 如果另一个 操作数的类型为sbyte、short、int, 或长。
    • 否则,如果其中一个操作数是long类型,则另一个操作数是 已转换为长类型。
    • 否则,如果其中一个操作数为uint类型,而另一个操作数为 类型sbyte、short或int,两者都是 操作数转换为长类型。
    • 否则,如果其中一个操作数是uint类型,则另一个操作数是 已转换为uint类型。
    • 否则, 两个操作数都转换为int类型 .

    所以,基本上操作数小于 int 将转换为 int 对于这些运算符(结果将是 int 对于非关系操作)。

    我说我不能给你一个理由;但是,我会猜一个——我认为C的设计者想要确保如果缩小的话可能会丢失信息的操作需要由程序员以强制转换的形式显式的缩小操作。例如:

    byte a = 200;
    byte b = 100;
    
    byte c = a + b;  // value would be truncated
    

    虽然在两个字节操作数之间执行异或操作时不会发生这种截断,但我认为语言设计者可能不希望有一组更复杂的规则,其中一些操作需要显式的强制转换,而另一些则不需要。


    只是一个小提示:上面的引用是“信息性的”而不是“规范性的”,但是它以易于阅读的形式涵盖了所有的案例。严格来说(在规范意义上),原因是 ^ 运算符的这种行为是因为在处理 byte 操作数是(来自14.10.1“整数逻辑运算符”):

    int operator ^(int x, int y); 
    

    因此,正如信息文本所解释的,操作数被提升为 int 和一个 int 结果就产生了。

        2
  •  2
  •   Michael Buen    14 年前

    微软的半神程序员有一个答案: http://blogs.msdn.com/oldnewthing/archive/2004/03/10/87247.aspx

    也许这更多的是关于编译器的设计。它们通过归纳编译过程使编译器更简单,它不必查看操作数的运算符,因此它将位操作集中在与算术运算符相同的类别中。因此,在类型加宽的情况下

        3
  •  1
  •   Gishu    14 年前

    我猜是因为操作符xor是为布尔值和整数定义的。

    将整数结果转换为字节的结果是一种信息丢失转换,因此需要显式转换(程序员的nod)。

        4
  •  0
  •   James Webster Jonathan Wood    14 年前

    这与cli规范中有关隐式和显式强制转换的规则有关。整数(int=system.int32=4字节)比字节(显然是1字节)宽。因此,从int到byte的任何转换都可能是一个收缩转换。因此,编译器希望您将其显式化。

        5
  •  0
  •   Community    7 年前

    我想我记得一个关于这个的流行问题。

    byte + byte = int... why?

        6
  •  0
  •   Omer Akhter    14 年前

    这似乎是因为在C语言规范中,它是为整型和长型定义的 http://msdn.microsoft.com/en-us/library/aa691307%28v=VS.71%29.aspx

    因此,实际发生的情况是编译器将字节操作数隐式地强制转换为int,因为这样不会丢失数据。但如果不丢失数据(隐式地),则无法向下转换结果(int)。所以,您需要明确地告诉编译器您知道自己在做什么!

        7
  •  0
  •   Damien_The_Unbeliever    14 年前

    为什么两个字节必须转换成整数才能执行XOR?

    如果您想深入研究它,cli规范(分区i)的12.1.2描述了这样一个事实:在评估堆栈上,只能存在int或long。在评估过程中,所有较短的积分类型都必须扩展。

    不幸的是,我找不到直接指向cli规范的合适链接-我有一个本地的PDF副本,但不记得从哪里得到的。

        8
  •  -1
  •   Dan Honeycutt    8 年前

    FWW 字节A=25; 字节B=60; a= a^ b; 不起作用。然而 字节A=25; 字节B=60; a^=B; 工作。