0

这条看似微不足道的行来自 C 书 my Mike Banahan & Brady (Section 2.8.8.2)

我可以理解隐式提升是如何在表达式中发挥作用的,例如c=a+b取决于操作数的类型,但我无法理解如何以及在何种情况下同样可以出现在类似的东西中-b,其中b是任何合法的操作数。你能解释一下,然后举一个恰当的例子吗?

提取的文本如下:

通常的算术转换适用于运算符的二进制形式的两个操作数。仅对运算符的一元形式的操作数执行整数提升。

更新:

为了避免被忽视,我在这里根据 OUAH 在评论中的回答添加了我所问的内容——这本书说' Only the integral promotions are performed'......这是否意味着在这样的表达式x=-y中,'x' 是一个长双精度数,而 'y' 是如果我们明确使用一元运算符,浮点数,'y' 不会被提升为长双精度数?我知道会是这样,但仍然要求它更清楚地了解“仅整数促销......”部分。

更新:

您能否举例说明以下按位运算符的提升是如何发挥作用的?对于最后三个,我是否应该假设每当在变量上使用它们时,它首先被提升为整数类型?前三个“通常的算术转换”到底是什么意思?你能举个小例子吗?如果可以在这里解决,我不想将其作为单独的问题发布。

在此处输入图像描述

4

4 回答 4

3

以 32 位系统为例:

 unsigned char a = 42;

 printf("%zu\n", sizeof a);   // prints 1

 printf("%zu\n", sizeof +a);  // prints 4, a has been promoted to int
于 2014-09-21T15:42:11.770 回答
2

对于一元算术运算符,C 标准说(在第 6.5.3.3 节中)

整数提升在操作数上执行,结果具有提升的类型。

它还在第 6.3.1.1 节中定义了该术语:

如果 anint可以表示原始类型的所有值(受宽度限制,对于位域),则该值将转换为int; 否则,将其转换为unsigned int. 这些被称为整数促销。整数提升不会改变所有其他类型。

(参考 2011 C 标准的N1570 草案。)

我相信这样做的理由是实现不需要支持任何比int(一个“单词”)更窄的类型的算术运算。比 an 窄的操作数在对其进行操作之前int转换为int或。unsigned int

对于二元运算符(采用两个操作数的运算符),还有一个附加要求,即两个操作数必须是相同的类型。典型的 CPU 可能有指令将两个 32 位有符号整数相加,或两个 32 位无符号整数,或两个 64 位有符号或无符号整数相加,但没有一个指令会直接相加,例如,一个 32 位有符号整数和一个64 位无符号整数。为此,我们有通常的算术转换,如 6.3.1.8 节所述。例如,这些规则告诉您,当您尝试将 an 添加int到 a时会发生什么doubleint操作数通过转换提升为 type double,并且添加结果将两个double操作数相加。

移位运算符不需要通常的算术转换,因为没有特别需要两个操作数属于同一类型。左操作数是要操作的值;右操作数指定要移动它的位数。

这是否意味着如果我们显式使用运算符x=-y,在诸如 where xis along doubleyis a这样float的表达式y中将不会被提升为?long doubleunary

赋值导致右操作数转换为左操作数的类型。表达式-y的计算独立于它出现的上下文(对于大多数表达式都是如此)。所以一元-应用于它的操作数,它是类型float的(整数提升不影响它),产生类型的结果float。该赋值导致该值在被赋值之前被float转换为。long doublex

您的问题的标题询问这怎么可能发生。我不确定那是什么意思。转换规则在语言标准中指定。编译器遵循这些规则。

于 2014-09-21T19:41:41.527 回答
0

我不确定,但我认为每个操作都被提升为适当的类型。首先转换完成,然后操作完成。该-b操作改变了结果变量的值,所以应该进行提升,然后转换值符号。

像操作一样+b也是操作,所以有一个Promotion + Operation的过程。我不知道在这种具体情况下代码优化是否可以跳过这个过程。

于 2014-09-21T15:57:59.877 回答
0

在使用二元运算符的操作期间,将算术提升到最需要的形式,从 int 到 long、float 或 double。

double c=2+3.5

但在一元运算符+中,-只允许整数类型数据类型的提升。从短到整数或长。

unsigned char a=255;
cout<<sizeof(a)<<endl; //prints 1
cout<<sizeof(+a)<<endl; //prints 4
cout<<sizeof(++a)<<endl; //prints 1

所以这个 Integral promtions 不适用于其他一元运算符++aa++

于 2014-09-21T16:25:00.367 回答