c# - 从整数到整数的转换方式有区别吗?

标签 c# c++ casting bit-manipulation d

当我想将一个整数(例如 32 位整数/int)转换为另一种整数类型(例如 8 位整数/字节)时有区别吗?下面是我可以转换它的两种方式的一些示例代码:

byte foo(int value)
{
    //return value; <-- this causes problems because I need to convert it to byte

   //First way(most people use this):
   return (byte)value; //this involves casting the value and also works if value is floating point type

   //Second way:
   return value & byte.MaxValue; //byte.MaxValue is a constant that is 255
}

那么这两者有什么区别吗?我知道按位运算只适用于整数类型。我知道第二种方式不太可读或不推荐。除了这两种方式的输出有任何差异。这不仅适用于 int 和 byte,还适用于每个整数-整数类型组合。

好吧,看来这个操作在不同的语言中有不同的行为。我不想看到差异,所以请发布 C++/C#/D 的答案。

另外我忘了我的意思是仅无符号整数(未签名)。所以它适用于所有无符号整数类型。

最佳答案

在 C# 中,如果它在 checked 上下文中超出 and 范围,则将 int 转换为 byte 将引发异常。否则,转换的行为与 C++ 非常相似。

类型提升在 C# 中的工作方式与在 C++ 中一样(如 Mark B 所述)。

为了对比,看一下这三种方法生成的IL:

byte foo1(uint value)
{
    return (byte) value;
}

.method private hidebysig instance uint8 foo1(int32 'value') cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: conv.u1 
    L_0002: ret 
}

对比

byte foo2(uint value)
{
    checked
    {
        return (byte)value;
    }
}

.method private hidebysig instance uint8 foo2(uint32 'value') cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: conv.ovf.u1.un 
    L_0002: ret 
}

对于 ANDing:

byte foo3(int value)
{
    return (byte)(value & byte.MaxValue);
}

.method private hidebysig instance uint8 foo3(uint32 'value') cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: ldc.i4 255
    L_0006: and 
    L_0007: conv.u1 
    L_0008: ret 
}

这再次使用了 conv.u1,就像第一种方法一样,所以它所做的只是引入了开销,并删除了被 conv.u1 忽略的额外位> 无论如何说明。

因此在 C# 中,如果您不关心范围检查,我只会使用转换。

一件有趣的事情是,在 C# 中,这会给你一个编译器错误:

Trace.Assert(((byte)256) == 0); // Compiler knows 256 is out of range.

这不会给出编译错误:

int value = 256;
Trace.Assert(((byte)value) == 0); // Compiler doesn't care.

当然这也不会给出编译错误:

unchecked
{
    Trace.Assert(((byte)256) == 0);
}

奇怪的是第一个给出了一个编译器错误,即使默认情况下它在运行时是未检查的。我想默认情况下会检查编译时!

关于c# - 从整数到整数的转换方式有区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16567424/

相关文章:

c++ - typedefing 函数返回类型

java - 将对象转换为 map : Cast vs ObjectMapper

c# - 重新排序集合我做错了什么?

c# - 绑定(bind) IsPaneOpen 解决 bool 属性问题

c++ - "operations.hpp"中的 OpenCV 2.4.2 编译问题

java - 按实际类型使用方法

c - 如何计算结构的偏移量?在这里解释一下 printf 语句?

c# - 我如何将数据集的表/对象列表发送到客户端应用程序?

c# - 当我在派生类中时,如何 "unbind"附加到基类中事件的事件处理程序?

c++ - GLSL和c有什么区别?