90

In C, it's legal to write something like:

int foo = +4;

However, as far as I can tell, the unary plus (+) in +4 is a no-op. Is it?

zneak
  • 134,922
  • 42
  • 253
  • 328
  • Not exactly the same, but related: http://stackoverflow.com/questions/727516/what-does-the-unary-plus-operator-do – jglouie Jul 09 '11 at 19:33
  • 5
    http://msdn.microsoft.com/en-us/library/s50et82s.aspx "The unary plus operator preceding an expression in parentheses forces the grouping of the enclosed operations. It is used with expressions involving more than one associative or commutative binary operator. The operand must have arithmetic type. The result is the value of the operand. An integral operand undergoes integral promotion. The type of the result is the type of the promoted operand." – Tim S. Jul 09 '11 at 19:36
  • 6
    K&R says it was just added for symmetry in the standard. – Aaron Yodaiken Jul 10 '11 at 02:44
  • 2
    @Jeremy: there is. E.g. it says that `+short(1)` has type `int`, not `short`. – MSalters Jul 11 '11 at 10:19
  • @Jeremy, re: Tim S. Check the source. Did you here the one about the airplane? :) – luser droog Aug 12 '11 at 15:28
  • 1
    @TimS.: "*The unary plus operator preceding an expression in parentheses forces the grouping of the enclosed operations*" -- Oh? It's the parentheses, not the `+`, that forces the grouping. – Keith Thompson Jun 30 '13 at 22:24
  • @MSalters: `+short(1)` is a syntax error. Were you thinking of `+(short)1`? – Keith Thompson Jun 30 '13 at 22:25
  • Bjarne Stroustroup supplied an explanation in his calculator language in one of his books, paraphrased "when there's unary minus, someone always tries to do unary plus, so it's easier to just implement it than to explain why it's useless." – Brandin Jun 26 '17 at 08:12

8 Answers8

84

You can use it as a sort of assertion that an expression has arithmetic type:

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

This will generate a compile-time error if x evaluates to (say) a pointer.

That is about the only practical use I can think of.

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • 7
    You can also cast an enum value to its integer value this way. – GManNickG Jul 09 '11 at 21:14
  • Just make sure to document that, because that is *completely* non-obvious – BlueRaja - Danny Pflughoeft Jul 09 '11 at 22:48
  • 2
    Why can't you do the same thing with, for example, `(-(-(x)))`? – Aaron Yodaiken Jul 10 '11 at 01:06
  • @luxun, I'm fairly sure you can. – zneak Jul 10 '11 at 02:47
  • @GMan, isn't the enum to int conversion implicit in C? – zneak Jul 10 '11 at 02:48
  • @zneak: Yes, but with this you can do the conversion without having to specify the target type. There's no way to know, in general, the underlying type. – GManNickG Jul 10 '11 at 03:37
  • 8
    @luxun @zneak: Interesting idea... Let me see... OK, how about this. If `int` is 32-bit and `x` happens to be an `int` equal to `-2^31`, then `-x` will overflow a signed integer which is technically Undefined Behavior. :-) – Nemo Jul 10 '11 at 03:40
  • @Nemo, the point being to trigger a compile-time error, as long as `CHECK_ARITHMETIC` isn't used in any assignment, I'm all right with that :) – zneak Jul 10 '11 at 03:49
  • 4
    @zneak: The point is to trigger a compile time error if the expression has pointer type, but to be a no-op if it has arithmetic type. Your version does fine, except for arithmetic expressions that happen to evaluate to `INT_MIN`. (Well, in theory, anyway. In practice it probably works fine on any realistic machine.) Still, a strict reading of the standard says these are different. – Nemo Jul 10 '11 at 05:34
  • I meant that you can just do `CHECK_ARITHMETIC(x);` without using it in an assignment to get the compile error, and use `x` directly after that. – zneak Jul 10 '11 at 06:16
  • 1
    @zneak: Even if you do not use it in an assignment, merely to evaluate `-x` when `x` is `INT_MIN` is technically to invoke undefined behavior, I believe. – Nemo Jul 10 '11 at 06:31
  • The same happens for `#define CHECK_ARITHMETIC(x) (-(x))`. Unary + was added to the ANSI standard only for symmetry with unary -. – Priyank Bhatnagar Jul 10 '11 at 19:15
  • 1
    @logic_max: The point of the suggestion is to use `(+(x))` to assert that an expression has arithmetic type at compile-time. You _cannot_ use `(-(x))` or `(-(-(x)))` instead without risking undefined behavior. Not that this is particularly useful... And I am not claiming it was the rationale... But it is the only way to do it to my knowledge. – Nemo Jul 10 '11 at 20:15
  • @Nemo : Yes i get that,+1 for that. But, i don't think that (-(x)) will cause any undefined behavior. Both, unary + and - are not applicable on pointers, so both will generate compile time errors. The value at runtime has nothing to do with this. – Priyank Bhatnagar Jul 10 '11 at 22:20
  • 1
    You can use `-` just as well to assert arithmetic type as long as you don't **evaluate** the expression. For example, `(0&&-(x))`. If you want to ensure `x` is still evaluated, use `((x),(0&&-(x)))`. – R.. GitHub STOP HELPING ICE Sep 28 '11 at 00:57
42

As per the C90 standard in 6.3.3.3:

The result of the unary + operator is the value of its operand. The integral promotion is performed on the operand. and the result has the promoted type.

and

The operand of the unary + or - operator shall have arithmetic type..

lccarrasco
  • 2,031
  • 1
  • 17
  • 20
  • 1
    So `+x` is a noop unless `sizeof x < sizeof(int)`? – zneak Jul 09 '11 at 19:45
  • 36
    These quotes from the standard show that the unary + is not simply a no-op. It does perform integral promotion on the operand. And, possibly more importantly, it does turn an lvalue into an rvalue. – Sander De Dycker Jul 09 '11 at 19:48
  • Well, it's theoretically possible that `sizeof(short) == sizeof(int)` but a `short` has padding, and theoretically, on such a system the padding might need to be zeroed or sign extended. Theoretically. – Dietrich Epp Jul 09 '11 at 19:49
  • Note that when it says arithmetic type it refers to both Integral types and Floating types, the example Nemo shows works because pointers are outside this classification. Integral types and pointers form Scalar types. – lccarrasco Jul 09 '11 at 19:55
  • This doesn't affect a `float` or a `double` at all, does it? – S.S. Anne Jan 13 '20 at 22:28
38

There's one very handy use of the unary plus operator I know of: in macros. Suppose you want to do something like

#if FOO > 0

If FOO is undefined, the C language requires it be replaced by 0 in this case. But if FOO was defined with an empty definition, the above directive will result in an error. Instead you can use:

#if FOO+0 > 0

And now, the directive will be syntactically correct whether FOO is undefined, defined as blank, or defined as an integer value.

Of course whether this will yield the desired semantics is a completely separate question, but in some useful cases it will.

Edit: Note that you can even use this to distinguish the cases of FOO being defined as zero versus defined as blank, as in:

#if 2*FOO+1 == 1
/* FOO is 0 */
#else
/* FOO is blank */
#endif
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
20

I found two things that unary + operator do is

  • integer promotion
  • turning lvalue into rvalue

integer promotion example:

#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;
}

Typical output (on 64-bit platform):

1 2 4 8
4 4 4 8

turning lvalue into rvalue example:

int i=0,j;

j=(+i)++; // error lvalue required
Persixty
  • 8,165
  • 2
  • 13
  • 35
A.s. Bhullar
  • 2,680
  • 2
  • 26
  • 32
  • 1
    Finally. A potentially useful application that will inform some generic code of the size of an argument following integer promotion that may not be `sizeof(int)`. I've got no idea when I'll use it. But nice all the same. NB: edited answer to show that not everything goes to 4. – Persixty Sep 07 '17 at 11:08
18

Pretty much. It's mainly present for completeness, and to make constructions like this look a little cleaner:

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

Not precisely a no-op

The unary + operator does only one thing: it applies the integer promotions. Since those would occur anyway if the operand were used in an expression, one imagines that unary + is in C simply for symmetry with unary -.

It's difficult to see this in action because the promotions are so generally applied.

I came up with this:

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

which (on my Mac) prints

1
4
Delan Azabani
  • 79,602
  • 28
  • 170
  • 210
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
14

What is the purpose of the unary '+' operator in C?

Unary plus was added to C for symmetry with unary minus, from the Rationale for International Standard—Programming Languages—C:

Unary plus was adopted by the C89 Committee from several implementations, for symmetry with unary minus.

and it is not a no-op, it performs the integer promotions on its operand. Quoting from my answer to Does Unary + operator do type conversions?:

The draft C99 standard section 6.5.3.3 Unary arithmetic operators says:

The result of the unary + operator is the value of its (promoted) operand. The integer promotions are performed on the operand, and the result has the promoted type.

Worth pointing out that Annotated C++ Reference Manual(ARM) provides the following commentary on unary plus:

Unary plus is a historical accident and generally useless.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • In C++ it is also "abused" when a `static_cast` would show intent more clearly for example [Resolving ambiguous overload on function pointer and std::function for a lambda using +](https://stackoverflow.com/q/17822131/1708801) – Shafik Yaghmour Nov 30 '17 at 16:46
1

By 'no-op', do you mean the assembly instruction?
If so, then definitely not.

+4 is just 4 - the compiler won't add any further instructions.

DefenestrationDay
  • 3,712
  • 2
  • 33
  • 61