2

我对如何在定点环境中处理算术计算感到有些困惑。考虑以下代码行:

/* unsigned short is 16 bit.*/
unsigned short x = 1000;
unsigned short res;

/* Case1: The following yields correct result  in res */
res = (x*544/100);

/* Case2: The following yields wrong result in res*/
res = (x*544); /* expected overflow here */
res = res/100;

所以,我的问题是:我明白为什么案例 2 会产生错误的结果。但是 - 编译器在产生正确结果的情况 1 中做了什么?- 在情况 1 中算术运算本质上不是一样的吗?除了,它分为两个语句?- 我可以期待不同编译器的不同行为吗?

4

2 回答 2

5

这是由于通常的算术转换被应用于乘法操作数,然后是除法,这导致为了计算的目的将short提升为更大的整数类型,然后在赋值时转换为short 。

乘法运算符部分中的C99 标准草案说:6.5.5

通常的算术转换是在操作数上执行的。

我们还需要注意整数常量544并且100将具有int类型,我们可以在问题中找到有关为什么默认整数值是什么的详细信息?.

然后,我们可以转到6.3.1.8 通常的算术转换部分,我们最终会看到以下段落:

否则,对两个操作数都执行整数提升。然后将以下规则应用于提升的操作数:

我们最终得到以下规则:

否则,如果有符号整数类型的操作数的类型可以表示无符号整数类型的操作数的所有值,则将无符号整数类型的操作数转换为有符号整数类型的操作数的类型。

所以计算的结果是一个int

使用该-Wcoversion标志gcc但令人惊讶的是不会clang产生警告:

warning: conversion to 'short unsigned int' from 'int' may alter its value [-Wconversion]
res = (x*544/100);
      ^

这会导致您在第一种情况下称为正确结果,因为在第二种情况下,所有计算都以int形式完成,您会丢失乘法的中间结果,因为您将其分配回res并将值转换为适合的值简而言之。_

于 2014-09-12T18:37:55.127 回答
-3

程序首先计算赋值的右边部分,然后赋值计算的值。

在第一个示例中,它在分配之前计算值,以便res实际存储它。

第二个例子res = (x*544);中不能容纳这么大的值并且它溢出了。

总之,在分配之前,编译器并不关心你是否通过了 short 的界限。

于 2014-09-12T18:31:44.433 回答