tags:

views:

578

answers:

12

What is the difference between int* i and int** i?

+10  A: 

int* pi

pi is a pointer to an integer

int **ppi

ppi is a pointer to a pointer to an integer.

EDIT :

You need to read a good book on pointers. I recommend Pointers on C by Kenneth Reek.

Prasoon Saurav
+19  A: 

Pointer to an integer value

int* i


Pointer to a pointer to an integer value

int** i

(Ie, in the second case you will require two dereferrences to access the integer's value)

RJFalconer
+6  A: 
  • int* i : i is a pointer to a object of type int
  • int** i : i is a pointer to a pointer to a object of type int
  • int*** i : i is a pointer to a pointer to a pointer to object of type int
  • int**** i : i is a pointer to a pointer to a pointer to a pointer to object of type int
  • ...
Klaim
*"...pointer to a variable..."* Not necessarily a variable. The word "variable" in this context probably obscures the meaning a bit, in fact.
T.J. Crowder
@T.J. Crowder: even a const variable is a variable. It may get a different value each time it's created.
Nathan Fellman
@Nathan Not in `new int`. There is no variable here. Replacing `variable` by `object` would be appropriate.
Johannes Schaub - litb
If it's `C` and not `C++`, a `const` value isn't even necessarily constant.
detly
I'm not sure to see the difference between object and variable (as variable is an adjective implying object) but I replaced it anyway.
Klaim
Simply, an object is a typed region of storage; a variable is introduce by the declaration of an object. The name of the variable denotes the object but you can create objects without using a variable (e.g. through dynamic allocation). Further, in C++0x variables may be references or objects, technically a reference isn't a variable in C++03.
Charles Bailey
So in a nutshell, variables are objects that have a name.
Johannes Schaub - litb
To add insult to injury, pointers are objects ("typed regions of storage"), too. `:)`
sbi
Oh ok. For me unammed variables where unnamed objects. Anyway I guess we should follow the standard's definitions.
Klaim
@litb: I've always thought of _variable_ as refering to the name more than the object (or reference) itself but the standard is more than a little vague. It says that a _variable_ is "introduced" by by a declaration and that it's name denotes the reference or object declared. So we know when a _variable_ is introduced and what its name denotes but not really what it is.
Charles Bailey
@Charles The Standard at 1.8 says "An object can have a name (Clause 3).". So ultimately, i think we could equivalently say "a named object is introduced ..." and that the name of the object denotes that object. c.f. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2993.html . In the various sections of the C++03 Standard, it always uses "variable" in the meaning of "named object" (modulo references), not in the meaning of "an entity that can be used to denote an object" (c.f. 3.2/1) and C++0x removed "Variable" from the entity list of clause 3.
Johannes Schaub - litb
Interesting that they removed one of the words to be more explicit.
Klaim
+5  A: 

I don't think this is specific to opencv.

int *i is declaring a pointer to an int. So i stores a memory address, and C is expecting the contents of that memory address to contain an int.

int **i is declaring a pointer to... a pointer. To an int. So i contains an address, and at that memory address, C is expecting to see another pointer. That second memory address, then, is expected to hold an int.

Do note that, while you are declaring a pointer to an int, the actual int is not allocated. So it is valid to say int *i = 23, which is saying "I have a variable and I want it to point to memory address 23 which will contain an int." But if you tried to actually read or write to memory address 23, you would probably segfault, since your program doesn't "own" that chunk of RAM. *i = 100 would segfault. (The solution is to use malloc(). Or you can make it point to an existing variable, as in int j = 5; int *i = &j)

rascher
+1  A: 

Let's say you're a teacher and have to give notes to one of your students.

int note;

Well ... I meant the whole class

int *class_note; /* class_note[0]: note for Adam; class_note[1]: note for Brian; ... */

Well ... don't forget you have several classes

int **classes_notes; /* classes_notes[0][2]: note for Charles in class 0; ... */

And, you also teach at several institutions

int ***intitute_note; /* institute_note[1][1][1]: note for David in class 1 of institute 1 */

etc, etc ...

pmg
Pointers are not always pointing to arrays.
luiscubal
@luiscubal: where is an array in my code (not the comments)?
pmg
@pmg Precisely in the comments.
luiscubal
This doesn't explain anything to a beginner.
Joren
+1  A: 

Neither is a declaration. Declaration syntax does not allow () around the entire declaration. What are these () doing there? If this is supposed to be a part of function declaration, include the whole function declaration thing in your question, since in general case the actual meaning of a declaration might depend on that. (Not in this one though.)

As for the difference... There is one * in the first and there are two *s in the second. Does it help? Probably not. The first one declares ias a pointer to int. The second one declares i as a pointer to int *. Does this help? Probably not much either. Without a more specific question, it is hard to provide a more meaningful answer.

Provide more context, please. Or, if this is actually as specific as it can get, read your favorite C or C++ book about pointers. Such broad generic questions is not something you ask on the net.

AndreyT
Not quite the response I'd expect from you. Not my dv tho.
John Dibling
@John not my dv either, but exactly the response I would expect from @AndreyT :)
Johannes Schaub - litb
Hm... I'm being grumpy after another `size_t` battle...
AndreyT
+2  A: 

Imagine you have a few friends, one of them has to give you something (a treasure... :-) Say john has the treasure

int treasure = 10000; // in USD, EUR or even better, in SO rep points

If you ask directly john

int john = treasure;
int you = john;

If you cannot join john, but gill knows how to contact him,

int john = treasure;
int *gill = &john;
int you = *gill;

If you cannot even join gill, but have to contact first jake who can contact gill

int john = treasure;
int *gill = &john;
int **jake = &gill;
int you = **jake;

Etc... Pointers are only indirections.

That was my last story for today before going to bed :-)

ring0
+3  A: 

I deeply believe that a picture is worth a thousand words. Take the following example

// Finds the first integer "I" in the sequence of N integers pointed to by "A" . 
// If an integer is found, the pointer pointed to by P is set to point to 
// that integer. 
void f(int N, int *A, int I, int **P) {
  for(int i = 0; i < N; i++)
    if(A[i] == I) {
      // Set the pointer pointed to by P to point to the ith integer.
      *P = &A[i];
      return;
    } 
}

So in the above, A points to the first integer in the sequence of N integers. And P points to a pointer that the caller will have the pointer to the found integer stored in.

int Is[] = { 1, 2, 3 };

int *P;
f(3, &Is[0], 2, &P);
assert(*P == 2);

&P is used to pass the address of P to the function. This address has type int **, because it's the address of a pointer to int.

Johannes Schaub - litb
A: 

Note that

int *i

is not fully interchangeable with

int i[]

This can be seen in that the following will compile:

int *i = new int[5];

while this will not:

int i[] = new int[5];

For the second, you have to give it a constructor list:

int i[] = {5,2,1,6,3};

You also get some checking with the [] form:

    int *i = new int[5];
    int *j = &(i[1]);
    delete j;

compiles warning free, while:

    int i[] = {0,1,2,3,4};
    int j[] = {i[1]};
    delete j;

will give the warnings:

warning C4156: deletion of an array expression without using the array form of 'delete'; array form substituted warning C4154: deletion of an array expression; conversion to pointer supplied

Both of these last two examples will crash the application, but the second version (using the [] declaration type) will give a warning that you're shooting yourself in the foot.

(Win32 console C++ project, Visual studio 2010)

PatrickV
A: 

int* i is the address of a memory location of an integer
int** is the address of a memory location of an address of a memory location of an integer

ananswer
A: 

Textual substitution is useful here, but beware of using it blindly as it can mislead you (as in the advanced example below).

T var; // var has type T
T* var; // var has type "pointer to T"

This works no matter what T is:

int* var; // pointer to int
char* var; // pointer to char
double* var; // pointer to double

// advanced (and not pure textual substitution):
typedef int int3[3]; // confusing: int3 has type "array (of size 3) of ints"
                     // also known as "int[3]"
int3* var; // pointer to "array (of size 3) of ints"
           // aka "pointer to int[3]"

int (*var)[3]; // same as above, note how the array type from the typedef
               // gets "unwrapped" around the declaration, using parens
               // because [] has higher precedence than *
               // ("int* var[3];" is an array (size 3) of pointers to int)

This works when T is itself a pointer type:

typedef int* T; // T is a synonym for "pointer to int"
T* var; // pointer to T
        // which means pointer to pointer to int
// same as:
int** var;
Roger Pate
A: 

int* i; // i is a pointer to integer. It can hold the address of a integer variable.

int** i; // i is a pointer to pointer to integer. It can hold address of a integer pointer variable.

Anand Kumar