一元+/-运算符怎么可能在“-a”或“+ a”中引起整数提升,’a’是算术数据类型常量/变量?

这看似微不足道的一行来自C书我的Mike Banahan&Brady (第2.8.8.2节) 。

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

提取的文字如下:

通常的算术转换应用于运算符的二进制forms的两个操作数。 仅对运算符的一元forms的操作数执行整体促销。

更新:

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

更新:

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

在此处输入图像描述

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

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

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

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

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

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

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

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

这是否意味着在x=-y这样的表达式中,其中xlong doubleyfloat ,如果我们明确使用一unary符, y将不会被提升为long double

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

你问题的标题询问这可能发生的原因。 我不确定这意味着什么。 转换规则在语言标准中指定。 编译器遵循这些规则。

以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 

我不确定,但我认为每个操作都被提升为合适的类型。 首先完成转换,然后完成操作。 -b操作会更改结果变量的值,因此应该完成提升,然后转换值符号。

+b这样的操作也是一种操作,因此有一个Promotion + Operation过程。 我不知道代码优化是否会在这个具体案例中跳过此过程。

在使用二元运算符的操作期间,完成从最高需要的forms到int,long,float或double的算术提升。

 double c=2+3.5 

但是在一元运算符+-只允许使用Integer类型数据类型的促销。 从短到int或长。

 unsigned char a=255; cout< 

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