2

我有个疑问

当两个 16 位值加上最大值时,16 位机器会溢出吗?

我会详细说明

unsigned short a;
unsigned short b;
unsigned long  c;

c=(unsigned long)(a+b);

谈到 16 位处理器,累加器将是 16 位大小。上面的语句会不会有溢出?请说清楚。

4

2 回答 2

13

使用这些定义并假设unsigned short== 16 位和int== 16 位和unsigned long== 32 位(请注意,大小int很重要):

unsigned short a, b;
unsigned long  c;

这两个语句将做不同的事情:

c = (unsigned long)(a + b);
c = (unsigned long)a + b;

第一个——你展示的那个——将首先将数字添加为无符号短裤,丢弃任何溢出——然后扩展为无符号长。这可能就是你问的原因。第二个将a转换为无符号长整数,然后将两个数字相加,b在进行加法之前也扩展为无符号长整数。

你也可以这样做:

c = (unsigned long)a + (unsigned long)b;

但这是不必要的,因为计算中存在一个 unsigned long 会导致另一个自动从 short 提升到 long 大小。

因此:

a = 0x8001;
b = 0x8001;
c = (unsigned long)(a + b);   /* c is assigned 0x00000002 */
c = (unsigned long)a + b;     /* c is assigned 0x00010002 */

所有这些都取决于您的特定编译器及其变量的大小。它具体取决于int编译器的大小,因为所有值都会自动提升到计算中intunsigned int在计算期间。您提到了具有 16 位累加器的硬件,而 C 编译器通常(但并非总是)使用本机寄存器大小作为 的大小int,这就是我假设 aint为 16 位的原因。

于 2009-04-29T12:44:13.100 回答
9

是的,会有溢出。子表达式 a + b 的类型为 short,只有在它被求值后才会将结果转换为 long。做这个:

c = (unsigned long)a + b;

这将导致 a在加法发生之前被强制转换为 long ,这反过来也会导致 b 也被强制转换为 long。因此,发生了两个 long 的相加,并且不会发生溢出。

于 2009-04-29T12:41:35.930 回答