当前位置: 首页 > 知识库问答 >
问题:

一元/-运算符如何可能导致“-a”或“a”中的整数提升,“a”是算术数据类型常量/变量?

柯镜
2023-03-14

这句看似微不足道的台词摘自我的迈克·巴纳汉的C书

我可以理解隐式提升是如何根据操作数的类型在诸如c=ab之类的表达式中发挥作用的,但我无法理解在诸如-b之类的表达式中,隐式提升是如何以及在何种情况下发挥作用的,其中b是任何合法的操作数。你能解释一下,然后给出一个恰当的例子吗?

摘录如下:

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

更新:

为了避免被忽视,我在这里添加了我根据OUAH在评论中的回答提出的问题–书中说,“只有整体促销才会执行””。。。这是否意味着在像x=-y这样的表达式中,如果我们显式使用一元运算符,“x”是长双精度,而“y”是浮点型,则“y”不会提升为长双精度?我知道会的,但还是要求它更清楚地了解“只有整体促销…”部分

更新:

你能举例解释一下推广是如何在下面的位运算符中发挥作用的吗?对于最后三个,我是否应该假设无论何时在变量上使用这些,它都首先被提升为整数类型?对于前三个,“通常的算术转换”到底意味着什么?你能举个小例子吗?如果能在这里解决,我不想把它作为一个单独的问题发布。

共有3个答案

吕新
2023-03-14

我不确定,但我认为每一个操作都是升级到一个合适的类型。首先进行转换,然后进行操作。-b操作更改结果变量的值,因此应进行升级,然后转换值符号。

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

葛景龙
2023-03-14

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

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

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

如果int可以表示原始类型的所有值(对于位字段,受宽度限制),则将该值转换为int;否则,将转换为无符号int。这些被称为整数提升。所有其他类型通过整数提升保持不变。

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

我相信这样做的基本原理是,实现不需要支持比int(一个“字”)更窄的类型上的任何算术运算。小于int的操作数在操作之前会转换为int,或转换为无符号int

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

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

这是否意味着在像x=-y这样的表达式中,xlong doubleyfloaty如果我们显式使用unary操作符,就不会提升为long double

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

你问题的标题是问这怎么可能发生。我不知道那是什么意思。语言标准中规定了转换规则。编译器遵循这些规则。

史高阳
2023-03-14

以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
 类似资料:
  • C++是静态语言:所有变量的类型,都会在编译时被准确指定。所以,作为程序员你需要为每个变量指定对应的类型。 有些时候就需要使用一些繁琐类型定义,比如: std::map<std::string,std::unique_ptr<some_data>> m; std::map<std::string,std::unique_ptr<some_data>>::iterator iter=m.

  • 本文向大家介绍计算三元组(a,b,c)的数量,以使C ++中a ^ 2 + b ^ 2 = c ^ 2和1 <= a <= b <= c <= n,包括了计算三元组(a,b,c)的数量,以使C ++中a ^ 2 + b ^ 2 = c ^ 2和1 <= a <= b <= c <= n的使用技巧和注意事项,需要的朋友参考一下 我们得到一个整数n。目标是找到满足条件的三元组(3个数字一组)- a 2

  • CP首选项说: 特别是,算术运算符不接受小于int的类型作为参数,如果适用,在左值到右值转换后,会自动应用整数提升。 所有主要的编译器(g、clang和msvc)都说,当a和b都是short时,decltype(a b)是int。 但是,标准说: 整数升级[conv.prom]/1整数转换秩小于int的整数类型的PR值可以转换为int类型的PR值。 常用的算术转换[表达式算术转换]/1.5.1 -

  • 问题内容: 我在Twitter上看到了这个Python代码段,并对输出感到困惑: 这里发生了什么? 问题答案: 从 Assignment语句 文档中 : 赋值语句评估表达式列表(请记住,它可以是单个表达式或逗号分隔的列表,后者产生一个元组),并将单个结果对象从左到右分配给每个目标列表。 您有两个分配目标列表;,和,该值从左到右分配给这两个目标。 首先,将元组解包到。您现在有和。注意这是可变的。 接

  • 问题内容: 我在该网站上遇到了这个问题,并在Eclipse中进行了尝试,但无法理解如何对其进行精确评估。 根据网站上的评论,x + = x * x * x ++解析为x = x +((x + 2)(x + 1) x),这是事实。我想我缺少有关此运算符优先级的信息。 问题答案: Java根据表达式的优先级从左到右计算表达式。 后缀递增运算符仅在使用/返回变量后递增该变量。一切似乎都是正确的。 这是后

  • 问题内容: 我刚刚发现了一个非常有趣的Java技巧: 因此,您可以根据需要为该方法提供尽可能多的整数。 现在,如果我有一个类似的(重载)方法,例如: 当我执行以下行时,运行哪种方法: 好吧,我可以通过使用不同的方法指令进行测试来轻松地发现这一点,但是当我考虑“重载”方法中的“规则”时,我必须确保每个重载的方法都必须相同,以便编译器知道确切地使用哪个。 我认为,上面的代码不起作用,因为应该混淆编译器