0

当我想将整数(例如 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 的答案。

我也忘了我的意思是无符号整数(无符号)。所以它适用于所有无符号整数类型。

4

2 回答 2

3

在 C# 中,如果将 int 转换为超出范围且checked上下文中的字节,则会引发异常。否则,强制转换的行为与 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);
}

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

于 2013-05-15T14:26:55.160 回答
0

在 C++ 中,结果的获取方式绝对不同,因为操作数 to&将提升为两种类型中较大者的大小。如果您使用的“最大值”&碰巧被签名,那么您将对扩展进行签名,并且按位运算可能不会产生预期的效果。

我个人更喜欢明确的return static_cast<char>(value);

于 2013-05-15T14:22:09.920 回答