【问题标题】:What is the purpose of the unary plus (+) operator in C?C中一元加号(+)运算符的目的是什么?
【发布时间】:2011-10-01 23:52:13
【问题描述】:

在 C 中,可以这样写:

int foo = +4;

但是,据我所知,+4 中的一元加号 (+) 是无操作的。是吗?

【问题讨论】:

  • 不完全相同,但相关:stackoverflow.com/questions/727516/…
  • msdn.microsoft.com/en-us/library/s50et82s.aspx "括号中表达式前面的一元加运算符强制对封闭运算进行分组。它用于涉及多个关联或交换二元运算符的表达式。操作数必须具有算术类型. 结果是操作数的值。整数操作数进行整数提升。结果的类型是提升的操作数的类型。"
  • K&R 说它只是为了在标准中添加对称性。
  • @Jeremy:有。例如。它说+short(1) 的类型为int,而不是short
  • @TimS.: "括号中表达式前面的一元加号运算符强制对封闭运算进行分组" -- 哦?强制分组的是括号,而不是 +

标签: c expression evaluation unary-operator


【解决方案1】:

您可以将其用作表达式具有算术类型的一种断言:

#define CHECK_ARITHMETIC(x) (+(x))

如果x 计算为(比如说)一个指针,这将产生一个编译时错误。

这是我能想到的唯一实际用途。

【讨论】:

  • 您也可以通过这种方式将枚举值转换为整数值。
  • 为什么你不能用(-(-(x)))做同样的事情?
  • @luxun @zneak:有趣的想法......让我看看......好吧,这个怎么样。如果 int 是 32 位的,而 x 恰好是等于 -2^31int,那么 -x 将溢出一个有符号整数,这在技术上是未定义的行为。 :-)
  • @zneak:关键是如果表达式具有指针类型则触发编译时错误,但如果它具有算术类型则为空操作。你的版本很好,除了算术表达式碰巧评估为INT_MIN。 (好吧,理论上,无论如何。实际上它可能在任何现实机器上都能正常工作。)不过,严格阅读标准表明这些是不同的。
  • @zneak:我相信,即使您不在作业中使用它,仅在 xINT_MIN 时评估 -x 从技术上讲就是调用未定义的行为。
【解决方案2】:

根据 6.3.3.3 中的 C90 标准:

一元+运算符的结果是其操作数的值。积分促销是 在操作数上执行。并且结果具有提升的类型。

一元 + 或 - 运算符的操作数应具有算术类型..

【讨论】:

  • 所以+x 是个空子,除非sizeof x < sizeof(int)?
  • 这些来自标准的引用表明一元 + 不仅仅是一个空操作。它确实对操作数执行积分提升。而且,可能更重要的是,它确实将左值变成了右值。
  • 嗯,理论上可能sizeof(short) == sizeof(int)short 有填充,理论上,在这样的系统上,填充可能需要归零或符号扩展。理论上。
  • 请注意,当它说算术类型时,它指的是 Integral 类型和 Floating 类型,Nemo 显示的示例有效,因为指针不在此分类范围内。整型和指针构成标量类型。
  • 这根本不会影响floatdouble,是吗?
【解决方案3】:

据我所知,一元加号运算符有一个非常方便的用法:在宏中。假设你想做类似的事情

#if FOO > 0

如果FOO 未定义,C 语言要求在这种情况下将其替换为 0。但是如果FOO 定义为空定义,则上述指令将导致错误。相反,您可以使用:

#if FOO+0 > 0

现在,无论FOO 是未定义、定义为空白还是定义为整数值,该指令在语法上都是正确的。

当然,这是否会产生所需的语义是一个完全独立的问题,但在某些有用的情况下会。

编辑:请注意,您甚至可以使用它来区分FOO 被定义为零和被定义为空白的情况,如下所示:

#if 2*FOO+1 == 1
/* FOO is 0 */
#else
/* FOO is blank */
#endif

【讨论】:

  • 你确定这些预处理器指令真的与 C 中的一元 + 运算符有关吗?在您的第二个示例中,使用空白 FOO,表达式将不是有效的 C。
  • 确实如此。在任何情况下,这对运算符 - - (空格必需!)据我所知相当于 +,这使得 + 相当多余......不,那是错误的,当操作数是INT_MIN... :-)
  • 很抱歉碰到这么老的答案,但这不是二进制加号而不是一元加号的例子吗?
  • @AuroraVollvik:如果恰好定义了宏但定义为空,则为一元加号。
  • @UndefinedBehavior:是一元还是二元取决于FOO是如何定义的。
【解决方案4】:

差不多。它主要是为了完整性,并使这样的结构看起来更简洁:

int arr[] = {
    +4,
    -1,
    +1,
    -4,
};

【讨论】:

  • 没有一元 +s 的情况,这绝对比替代方案更干净。
【解决方案5】:

我发现一元 + 运算符做的两件事是

  • integer promotion
  • turning lvalue into rvalue

整数提升示例:

#include <stdio.h>

int main(void) {

    char ch;
    short sh;
    int i;
    long l;

    printf("%d %d %d %d\n",sizeof(ch),sizeof(sh),sizeof(i),sizeof(l));
    printf("%d %d %d %d\n",sizeof(+ch),sizeof(+sh),sizeof(+i),sizeof(+l));
    return 0;
}

典型输出(在 64 位平台上):

1 2 4 8
4 4 4 8

将左值转为右值示例:

int i=0,j;

j=(+i)++; // error lvalue required

【讨论】:

  • 最后。一个潜在有用的应用程序,它将在可能不是sizeof(int) 的整数提升之后通知一些通用代码参数的大小。我不知道什么时候会使用它。但都很好。注意:编辑后的答案表明并非一切都到了 4。
【解决方案6】:

不完全是无操作

一元 + 运算符只做一件事:它应用整数提升。由于如果在表达式中使用操作数,无论如何都会发生这种情况,因此可以想象一元 + 在 C 中只是为了与一元 - 对称。

很难看到这一点,因为促销活动非常普遍。

我想出了这个:

printf("%zd\n", sizeof( (char) 'x'));
printf("%zd\n", sizeof(+(char) 'x'));

哪个(在我的 Mac 上)打印

1
4

【讨论】:

  • 这对于在 C++ 中使用 std::cout 打印 chars 很有用。
【解决方案7】:

C 中一元“+”运算符的用途是什么?

为了与一元减号对称,将一元加号添加到 C 中,来自 Rationale for International Standard—Programming Languages—C

为了与一元减号对称,C89 委员会从多个实现中采用了一元加号。

而且它不是空操作,它在其操作数上执行整数提升。引用我对Does Unary + operator do type conversions?的回答:

C99 标准部分草案6.5.3.3 一元算术运算符 说:

一元+运算符的结果是它的(提升)的值 操作数。 整数提升在操作数上执行,并且 结果具有提升的类型。

值得指出的是,Annotated C++ Reference Manual(ARM) 提供了以下关于一元加的评论:

一元加号是历史性的意外,一般来说是无用的。

【讨论】:

【解决方案8】:

“no-op”是指汇编指令吗?
如果是,那肯定不是。

+4 只是 4 - 编译器不会添加任何进一步的指令。

【讨论】:

  • “noop”是指“什么都不做”——我希望编译器不会为了添加指令而添加指令。
  • 但是+(char)4(char)4不一样。
猜你喜欢
  • 1970-01-01
  • 2010-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-03
  • 2012-08-21
  • 2010-12-11
相关资源
最近更新 更多