C语言中一元加(+)运算符的作用是什么?


77

在C语言中,编写类似以下内容是合法的:

int foo = +4;

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


不完全一样,但相关的:stackoverflow.com/questions/727516/...
jglouie

5
msdn.microsoft.com/zh-cn/library/s50et82s.aspx “括号中表达式前面的一元加运算符会强制对封闭的运算进行分组。它与涉及多个以上关联或可交换二进制运算符的表达式一起使用。操作数必须具有算术类型。结果是操作数的值。整数操作数经过整数提升。结果的类型是提升的操作数的类型。”
Tim S.

6
K&R说,它是为了对称性而添加的。
亚伦·尤代肯

2
@杰里米:有。例如,它说+short(1)有类型int,没有short
MSalters 2011年

1
@TimS .:“括号中表达式前面的一元加运算符会强制对封闭的操作进行分组” –哦?+强制分组的是括号而不是。
基思·汤普森

Answers:


34

根据6.3.3.3中的C90标准:

一元+运算符的结果是其操作数。整数提升是在操作数上执行的。结果为提升类型。

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


1
+x除非这样,否则没有人sizeof x < sizeof(int)吗?
zneak 2011年

31
这些来自标准的引号表明,一元+不仅仅是空无一物。它确实对操作数执行整数提升。而且,可能更重要的是,它确实将左值变成右值。
Sander De Dycker 2011年

嗯,从理论上讲可能有填充,sizeof(short) == sizeof(int)但从short理论上讲,在这样的系统上,填充可能需要清零或扩展符号。从理论上讲。
Dietrich Epp

请注意,当说算术类型时,它同时指整数类型和浮点类型,因此Nemo展示的示例有效,因为指针不在此分类之内。整数类型和指针构成标量类型。
lccarrasco 2011年

这并不影响一个floatdouble所有,不是吗?
SS安妮

77

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

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

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

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


7
您还可以通过这种方式将枚举值转换为其整数值。
GManNickG 2011年

2
例如,为什么您不能做同样的事情(-(-(x)))
亚伦·尤代肯

8
@luxun @zneak:有趣的主意...让我看看...好吧,这怎么样。如果int为32位并且x恰好int等于-2^31-x则将溢出一个有符号整数,这在技术上是未定义行为。:-)
Nemo

4
@zneak:关键是如果表达式具有指针类型,则触发编译时错误,但如果其具有算术类型,则变为无操作。您的版本运行良好,除了碰巧算作的算术表达式INT_MIN。(嗯,从理论上讲,无论如何。实际上,它在任何现实的机器上都可以正常工作。)不过,严格阅读该标准后,他们会有所不同。
Nemo

1
@zneak:我相信,即使您没有在分配中使用它,也只是评估技术上-x何时xINT_MIN调用未定义的行为。
Nemo

35

我知道一元加运算符非常方便使用:在宏中。假设您想做类似的事情

#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

1
您确定这些预处理程序指令确实与C中所见的一元+运算符相关吗?在你第二实例中,用空白FOO,表达式将是无效C.
zneak

2
确实如此。在任何情况下,据我所知,一对运算符- -(必不可少的空间!)等同于+,使它们变得+相当多余...不,这是错误的,当操作数为INT_MIN... :-)
R

2
很抱歉碰到这么老的答案,但这不是二进制加号而不是一元加号的例子吗?
奥罗拉Vollvik

2
@AuroraVollvik:如果宏恰好被定义但定义为空,则是一元加号。
R .. GitHub STOP HELPING ICE

2
@UndefinedBehavior:是一元还是二进制取决于FOO定义方式。
R .. GitHub STOP HELPING ICE

17

差不多了 主要是出于完整性的考虑,并且使这样的结构看起来更简洁:

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

1
这比没有一元符号+的替代方法更干净。
ruohola

14

不完全是无人值守

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

很难看到这一点,因为促销是如此普遍地应用。

我想出了这个:

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

(在我的Mac上)打印的

1
4

这对于使用charC ++在C ++中打印很有用std::cout
SS安妮

13

C语言中一元“ +”运算符的目的是什么?

国际标准原理(编程语言,C)中,一元加号被添加到C中以实现一元减号的对称性:

C89委员会从几种实现中采用了一元加号,以与一元减号对称。

它不是空操作,而是对其操作数执行整数提升。引用我对一元+运算符是否进行类型转换的回答 :

C99标准草稿6.5.3.3 一元算术运算符说:

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

值得指出的是,《带注释的C ++参考手册》(ARM对一元加号提供了以下注释:

一元加号是历史性事故,通常无用。


在C ++中,当astatic_cast会更清楚地显示意图时,它也被“滥用” ,例如,使用+
Shafik Yaghmour

13

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

  • 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

1
最后。一个潜在有用的应用程序,在整数提升之后可能会通知一些通用代码参数的大小sizeof(int)。我不知道何时使用它。但是很好。注:编辑答案表明,并非一切去4
Persixty

1

“无操作”是指汇编指令吗?
如果是这样,那绝对不是。

+4只是4-编译器不会添加任何其他指令。


2
“无用”是指“什么都不做”,我希望编译器不会为了添加指令而添加指令。
zneak 2011年

3
但是+(char)4不一样(char)4
DigitalRoss 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.