9

It just occurred to me That I don't know how to initialize a pointer to pointer from a non pointer value with one statement in C++:

int a = 1;
int** ppa = &&a; //Does not compile
int** ppa = &(&a); //Does not compile
int* pa = &a;   //Works but is a
int** ppa = &pa; //Two step solution

Am I missing something, is the two statement the one and only way to do it?

David Reis
  • 12,701
  • 7
  • 36
  • 42
  • 3
    Why do you think you need a pointer to a pointer, in this case? – SingleNegationElimination Sep 28 '10 at 07:55
  • possible duplicate of [How do pointer to pointers work in C?](http://stackoverflow.com/questions/897366/how-do-pointer-to-pointers-work-in-c) – Jens Gustedt Sep 28 '10 at 07:56
  • 1
    @Jens Gustedt, this is not a duplicate. Linked question asks about pointers in general. This question is about specific case. – Kirill V. Lyadvinsky Sep 28 '10 at 08:05
  • @TokenMacGuy : in what case? he's just given the simplest possible example to illustrate the question; there is no use case – Patrick Sep 28 '10 at 12:56
  • @Patric: that's my point. the poster has not explained what the pointer to pointer he's trying to initialize is supposed to *mean*. the expression `&&a` is certainly meaningless. – SingleNegationElimination Sep 28 '10 at 16:54
  • I also disagree this is a duplicate. I already knew how pointer to pointers worked, but was overlooking the (obvious) fact that you need to declare the actual intermediary pointer, which the answer to this question points out nicely. – David Reis Sep 30 '10 at 05:26

9 Answers9

15

if you want a pointer to a pointer, the pointer that you want to point to must be located somewhere in memory, so I think there cannot be a "one step solution" because you need a pointer variable that you can point to.

(Note: This sentence is not meant to be a linguistic trial to use "point" as often as possible in one sentence :-))

Philipp
  • 11,549
  • 8
  • 66
  • 126
14

You can't get pointer to a temporary. &a results in a r-value. It is allowed not to have an actual address.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
  • 1
    This is 100% correct, but I accepted Philip's answer instead because it goes into the rationale of why is that, rather than just pointing out to the standard. – David Reis Sep 30 '10 at 05:31
7

The many other are right: Your pointer to a pointer has to point to something. However, in C99 you can cheat by using compound literals:

int a = 1;
int **ppa = &(int *){ &a };

Compound literals are just basically unnamed objects and have the same storage rules as normal objects. (But you can't give a function scope compound literal static storage duration with the static keyword). You can even nest them so you can rewrite the previous example to a single line:

int **ppa =  &(int *) { &(int) { 1 } };
schot
  • 10,958
  • 2
  • 46
  • 71
  • This will most likely be undefined behavior and probably crash the application in the first use of the pointer. The compound literal is a temporary and the compiler can reuse that space, so `*ppa` points to `&a` during the execution of the second line, but might point to anything else afterwards. – David Rodríguez - dribeas Sep 28 '10 at 08:04
  • 1
    @David Rodriguez: No, your are wrong. The compound literal will have the same storage duration as `a` and `ppa`: Static when outside a function, automatic for the duration of the closing block otherwise. See C99 6.5.2.5 (6). – schot Sep 28 '10 at 08:09
  • 1
    You are completely right. I should have checked the standard before jumping into a comment... If at any point you modify the answer, comment and I will turn the -1 into a +1, it does not allow me to change it now. At any rate, depending on what you want to do with the pointer, it is *as dangerous* as the intermediate variable solution. – David Rodríguez - dribeas Sep 28 '10 at 08:22
  • @David Rodriguez: No problem. And indeed, pointers are always dangerous. The fact that the rules around compound literals are not well known is a reason to avoid these constructions. – schot Sep 28 '10 at 08:30
  • The rules around compound literals will only become well known if people use them. – caf Sep 28 '10 at 10:34
  • This indeed seems correct and does exactly what I wanted to begin with. However I feel its too esoteric to be used on a daily basis. – David Reis Sep 30 '10 at 05:36
5

C++03 [Section 5.3.1] says

The result of the unary &operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. In the first case, if the type of the expression is “T,” the type of the result is “pointer to T.”

In &&a, & operator cannot be applied to the result of &a because the result is not an lvalue.

Also read this thread

Community
  • 1
  • 1
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
3

You want a pointer (call it PP) to a pointer (call it P)?

Then P must actually exist. Which means you must declare it.

Of course the compiler will fail at &&a - because you can't take the address of an address. You can take the address of a pointer - but you'll have to declare the pointer first.

Thus:

int a = 1;
int *P = &a;
int **PP = &P;
PP.
  • 10,764
  • 7
  • 45
  • 59
  • 1
    The parser fails at `&&a` not because you can't take the address of an address but because `&&` is a single token which is not valid at this point in the declaration. `int **ppa = x &&a;` might be a valid initialization for a suitably typed `x` and a suitably overloaded `&&` (evil!) but it wouldn't be the address of an address. – CB Bailey Sep 28 '10 at 08:04
2

An address is a number. It only has an address of its own if it is held in a variable, i.e. a pointer. So

int *i1 = &a;

makes sense, but

int **i2 = &&a;

makes no sense. However

int **i2 = &i1;

does make sense. Make sense?

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    Your terminology is wrong. The address-of operator *does* yield a pointer, see [ISO03, 5.3.1 expr.unary.op §2]. It's common to call pointer *values* "addresses", and pointer *variables* "pointers", but strictly speaking, that is wrong. – fredoverflow Sep 28 '10 at 10:26
  • The terminology I used is in common use. The value of a pointer in the Standard's sense is an address in any sense, which in turn is a number in any sense. To put what I said another way, & doesn't yield a *variable,* so it doesn't yield anything whose address can be taken. – user207421 Sep 28 '10 at 10:33
0

When you do the following:

char a;
char* b = &a;
char** c = &b;

First of all a now exists on the stack. It obviously has a memory address (ie its stack position) this is what you assign to b. b now also exists on the stack and you can then pass its memory address to c. You cannot however take the address of the address of a value without the intermediate stack as it does not exist without explicitly creating it first.

Goz
  • 61,365
  • 24
  • 124
  • 204
0

The problem when you do something like &&a; is that you're asking for "the address of the address of a".

That doesn't make sense. We can get the address of a just fine, but that doesn't give us a variable we can take the address of. It just gives us a pointer value. Until that value is stored somewhere, we can't take its addres.

If you have code such as 2+2, the result doesn't have an address either. It is just the value 4, but it hasn't yet been stored anywhere, so we can't take an address. Once we store it into an int variable, we can take the address of that variable.

Basically, the problem is the difference between values and variables. A value is just a number (or a character, or some other data). A variable is a place in memory where a value is stored. A variable has an address, but a value doesn't.

In C++-speak, it is the difference between rvalues and lvalues. An rvalue is essentially a temporary, it's typically a value that was returned from another operation (such as the & operator in your case), but which hasn't yet been stored anywhere.

Once you store it into a variable, you get a lvalue, and lvalues have an address you can take.

So yes, you need the two separate statements. First you take the address, and then you store that address somewhere. And then you can take the address of this "somewhere".

jalf
  • 243,077
  • 51
  • 345
  • 550
  • Your terminology is wrong. The address-of operator *does* yield a pointer, see [ISO03, 5.3.1 expr.unary.op §2]. It's common to call pointer *values* "addresses", and pointer *variables* "pointers", but strictly speaking, that is wrong. – fredoverflow Sep 28 '10 at 10:25
  • @Fred: fair enough. I suspected I'd get in trouble over that. ;) That'll teach me to try to rephrase C++ semantics :p – jalf Sep 28 '10 at 10:28
  • Fixed it up a bit. Hope I got the most misleading bits. – jalf Sep 28 '10 at 10:30
-1

This might work:

int** ppa = &(int*){&a};

fileoffset
  • 21
  • 1