我有个疑问
当两个 16 位值加上最大值时,16 位机器会溢出吗?
我会详细说明
unsigned short a;
unsigned short b;
unsigned long c;
c=(unsigned long)(a+b);
谈到 16 位处理器,累加器将是 16 位大小。上面的语句会不会有溢出?请说清楚。
我有个疑问
当两个 16 位值加上最大值时,16 位机器会溢出吗?
我会详细说明
unsigned short a;
unsigned short b;
unsigned long c;
c=(unsigned long)(a+b);
谈到 16 位处理器,累加器将是 16 位大小。上面的语句会不会有溢出?请说清楚。
使用这些定义并假设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
编译器的大小,因为所有值都会自动提升到计算中int
或unsigned int
在计算期间。您提到了具有 16 位累加器的硬件,而 C 编译器通常(但并非总是)使用本机寄存器大小作为 的大小int
,这就是我假设 aint
为 16 位的原因。
是的,会有溢出。子表达式 a + b 的类型为 short,只有在它被求值后才会将结果转换为 long。做这个:
c = (unsigned long)a + b;
这将导致 a在加法发生之前被强制转换为 long ,这反过来也会导致 b 也被强制转换为 long。因此,发生了两个 long 的相加,并且不会发生溢出。