63

I saw a weird type of program here.

int main()
{
    int s[]={3,6,9,12,18};
    int* p=+s;
}

Above program tested on GCC and Clang compilers and working fine on both compilers.

I curious to know, What does int* p=+s; do?

Is array s decayed to pointer type?

Community
  • 1
  • 1
msc
  • 33,420
  • 29
  • 119
  • 214
  • 2
    That is exactly the purpose. This truck is also if you want to decay a lambda to a function pointer – MikeMB May 30 '18 at 07:01
  • 2
    Plus before `s` can be safely omitted, it has no effect – wl2776 May 30 '18 at 07:05
  • s is pointer to int, there is no such thing as "array type" in C. – ziza May 30 '18 at 07:05
  • 21
    There is array type in C. Try for example `sizeof` an array and a pointer. – Yksisarvinen May 30 '18 at 07:08
  • 8
    @ziza [arrays are completely different from pointers](https://stackoverflow.com/q/1641957/995714). For example if we have `int b[2]; int a* = b;` then `int *c = b+1` and `int *d = a + 1` will contain different values – phuclv May 30 '18 at 07:31
  • I would use `int* p = &s[0]`. But that's me. Actually, I would use `std::array`... – JHBonarius May 30 '18 at 07:55
  • 7
    And please, if you're going to write code like this, at least write it "int* p = +s" (with spaces around the '='), to make it clear that this was intended to be a unary '+', unless you're trying to confuse anyone who has to maintain this code... – Sean Burton May 30 '18 at 09:31
  • So you determine array size by using sizeof, but this is compile time operator and it works with statically allocated array. It is also possible to dinamically create array, what would be result of sizeof then? – ziza May 30 '18 at 09:39
  • 8
    @LưuVĩnhPhúc: [No they don't...?!?](https://ideone.com/uvo2CS) I agree arrays and pointers are different things, but your example is wrong. – DevSolar May 30 '18 at 10:44
  • 7
    It may be of anecdotal interest that [the `+=` operator originally was `=+`,](http://csapp.cs.cmu.edu/3e/docs/chistory.html) which was changed presumably exactly because of the ambiguity with the unary `+`. – Peter - Reinstate Monica May 30 '18 at 12:14
  • 3
    @LưuVĩnhPhúc @DevSolar is right. in `b+1` `b` decays to a pointer to its first element, i.e. is equal in type and value to `a`. If you want to point out (heh) the esistence of real arrays you could do something like `int *p = b; int (*pa)[2] = &b; cout << "p: " << p << "pa: " << pa << "p+1: " << p+1 << "pa+1: " << pa+1 << endl;` which should yield equal values for `p` and `pa` but different ones for the respective increments (because `pa` would point to the next *array* if there were one). – Peter - Reinstate Monica May 30 '18 at 12:25
  • 2
    @ziza No, that is not possible. A pointer is a pointer. The area pointed to is generally unknown. – Peter - Reinstate Monica May 30 '18 at 12:32
  • @ziza: You cannot apply `sizeof` to a dynamically allocated array because dynamically allocated array does not have a name. Also, this question is about C++, not about C. In C unary `+` is not applicable in this fashion, which would prevent the code from compiling. The question is exclusively about C++. – AnT stands with Russia May 31 '18 at 05:34
  • 1
    @SeanBurton If you're going to write code like this then put `int* p = std::decay(s);` – M.M May 31 '18 at 06:06
  • @M.M you meant `std::decay_t()`? – L. F. Dec 21 '19 at 11:13

5 Answers5

63

Built-in operator+ could take pointer type as its operand, so passing the array s to it causes array-to-pointer conversion and then the pointer int* is returned. That means you might use +s individually to get the pointer. (For this case it's superfluous; without operator+ it'll also decay to pointer and then assigned to p.)

(emphasis mine)

The built-in unary plus operator returns the value of its operand. The only situation where it is not a no-op is when the operand has integral type or unscoped enumeration type, which is changed by integral promotion, e.g, it converts char to int or if the operand is subject to lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversion.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Is it valid in C as well? – machine_1 May 30 '18 at 13:38
  • 5
    @machine_1 Sorry I don't know. I'm not familiar with C, they're different language. :) – songyuanyao May 30 '18 at 14:14
  • 4
    @machine_1 Not really. In C, the unary + operator converts `char` to `int` like in C++, but putting it before an array, a pointer, or a function isn't valid in C. – Donald Duck May 30 '18 at 16:16
  • @DonaldDuck: I think you mean putting it before pointer-type values, including array and functions *that decompose into such values and don't dereference the resulting pointer*. Given `double arr[20], someFunc(void), x;` code could perfectly legitimately do `x= +arr[5];` or `x = +someFunc();` since the array and function are dereferenced. – supercat May 30 '18 at 18:47
25

Test this:

#include <stdio.h>
int main(){
    char s[] = { 'h', 'e', 'l', 'l', 'o' , ' ', 'w', 'o', 'r', 'l', 'd', '!'} ;
    printf("sizeof(s) : %zu,  sizeof(+s) : %zu\n", sizeof(s), sizeof(+s) ) ;
}

On my PC (Ubuntu x86-64) it prints:

sizeof(s): 12,  sizeof(+s) : 8

where

12 = number of elements s times size of char, or size of whole array
 8 = size of pointer
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
11

That's a unary plus symbol which has no practical effect here. For example:

#include <iostream>

int main() {
    int a[] = {1};

    std::cout << a << " " << +a << std::endl;
}

This prints the same address for both a and +a. The array is decayed to pointer as usual.

Note that, if it had been an unary minus -a instead then GCC would show the error:

error: wrong type argument to unary minus

Edit: Though it has no effect in OP's code, a and +a are not exactly same. Please refer to the answers by Khurshid Normuradov and songyuanyao for details.

taskinoor
  • 45,586
  • 12
  • 116
  • 142
  • your answer is in constrast to most others by saying that "a unary plus symbol which has no practical effect here". However, `std::cout << a;` only prints the same because `operator<<` triggers the decay to a pointer as well, but still `a` is an array while `+a` is a pointer to the first element – 463035818_is_not_an_ai May 31 '18 at 00:08
  • hm I think your answer is correct insofar as in OPs code the `+` really has no practical effect, because (if i am not mistaken) already the `=` makes the array decay. Nevertheless your answer can be mistunderstood as `a` being the same as `+a`. – 463035818_is_not_an_ai May 31 '18 at 00:14
  • @user463035818 you are right. Other two answers cover that better than mine. So edited the answer a little bit to avoid such confusion. – taskinoor May 31 '18 at 06:22
10

Is array s decayed to pointer type?

Yes.

What does int* p=+s; do?

Unary + operator forces the array to decay to a pointer.

C++ Standard, 5.3.1 Unary operators(P7):

The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument. Integral promotion is performed on integral or enumeration operands. The type of the result is the type of the promoted operand.

The unary + form (+s) forces the operand to be evaluated as a number or a pointer.

For more information, please see this stack overflow answer.

msc
  • 33,420
  • 29
  • 119
  • 214
0

Here unary + is just making *p to point the addresses of Integer array. Let's take two array s1 and s2

int s1[]={1,5,2};
int s2[]={2,5,2};

int *p=+s1;
p=+s2; 
printf("%d",(int)p[0]);

Output: 2

So in my point of view unary + is just making pointer p to point the array s beginning address.

Mudassar
  • 508
  • 4
  • 13