关于c#:这会导致溢出吗?

Would this result in overflow? why and why not?

这会导致溢出吗?如果没有,那为什么不呢?因为"byte"类型的大小仍然是8位,如果它不会导致溢出,那么这是否意味着"casting"会将"byte"类型在内存中的分配从8位增加到32位?…最终,类型转换(隐式)是如何工作的?

1
2
3
4
5
6
7
//a part of c# program

byte b = 100;
b = (Byte)(b + 200);
Console.WriteLine("VALUE OF BYTE TYPE'S OBJECT {0}",b);

//end


如果表达式生成的值超出目标类型的范围,则结果将被截断。

如果您想知道您的代码是否产生溢出,您应该使用checked语句(msdn):

1
2
3
4
5
6
checked
{
    byte b = 100;
    b = (Byte)(b + 200);
    Debug.WriteLine("VALUE OF BYTE TYPE'S OBJECT {0}", b);
}


隐式转换是b+200。就像msdn-doc所说的那样,它隐式地变成了一个int,等于300。然后显式转换为字节,将其截断为8位。正如kmatyaszek所建议的,您可以在运行时在checked块内启用溢出检查。


见C语言规范:

7.6.12 The checked and unchecked operators

The following operations are affected by the overflow checking context
established by the checked and unchecked operators and statements:
...
? Explicit numeric conversions (§6.2.1) from one integral type to
another integral type, or from float or double to an integral type.

When one of the above operations produce a result that is too large to
represent in the destination type, the context in which the operation
is performed controls the resulting behavior:
...
? In an unchecked
context, the result is truncated by discarding any high-order bits
*that do not fit in the destination type*.

For non-constant expressions (expressions that are evaluated at
run-time) that are not enclosed by any checked or unchecked operators
or statements, the default overflow checking context is unchecked
unless external factors (such as compiler switches and execution
environment configuration) call for checked evaluation.

此-(byte)int进行显式数字转换,默认情况下在未选中的上下文中运行,因此截断结果。


不,因为当您执行显式强制转换时(并且由于它是隐式变为int的,所以您必须这样做),就像您对编译器说的"是的,我知道我在做什么,无论如何都要这样做",所以结果将是(300-256=44),因此要导致溢出异常,您需要在适当的try/catch块中添加这样的选中关键字:

1
2
3
4
5
6
7
8
9
10
try
{
   byte b = 100;
   b = checked((byte)(b + 200));
   Console.WriteLine("VALUE OF BYTE TYPE'S OBJECT {0}", b);
}
catch(OverFlowException e)
{
   Console.WriteLine(e.Message);
}


考虑您的代码片段,如下所示:

1
2
3
4
5
6
byte b = 100;
Console.WriteLine(b);

b = (Byte)(b + 200);

Console.WriteLine(b);

此代码将分别输出10044。当该代码执行时,实际发生的情况是,添加操作导致大于8位的值,但程序不关心,只接受最后1个字节(例如,32位值中的最后8位)。

编辑:请记住,执行该操作时,它不会导致溢出错误/异常。考虑代码:

1
2
3
4
b = Byte.MaxValue;
Console.WriteLine(b);
b++;
Console.WriteLine(b);

输出2550

但是,本规范将:

1
2
3
4
b = Byte.MaxValue;
Console.WriteLine(b);
b = checked((byte)(b + 1));
Console.WriteLine(b);

见:

  • 在C中转换为字节#
  • 字节+字节=整数…为什么?
  • 为什么C中的字节减法需要强制转换?