6
int num = 45,*ptr1,*ptr2;
ptr1=#
ptr2=&ptr1;
printf("%d\n",*ptr1);

I've been thinking about this question for a while, but couldn't find a way to understand it,why &ptr1 can not be assigned to ptr2 in line 3, &ptr1 is a pointer's address,this address is no different from other address like an address of an integer, say

int a=1;
ptr2=&a;

Which means that I can assign an integer's address to a pointer,but not a pointer's address to a pointer,what differences between these two "address" could possibly make them different? Address of common variables can be assigned to single pointer,but address of pointers can not be assigned to single pointer?

I know the right way to do it is use double pointer to declare ptr2,but why single pointer can't?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
user2556058
  • 311
  • 4
  • 9
  • You can assign integer address to integer pointer. If you want to assign pointer address, you need pointer to pointer type. It's about type safety. You can do what you want with brutal casting. – Alex F Jul 16 '13 at 15:03
  • You could also argue that an int should be good enough to store the address... – Maxime Chéramy Jul 16 '13 at 15:04
  • @Maxime except where it isn't - i.e. you could be on a 64-bit platform where all pointers must be 64-bit, yet integers are still 32-bit. Arguably not common, but it is a permitted configuration... – twalberg Jul 16 '13 at 15:15
  • Well, I like to think about it in the following terms: If you want two pointers pointing to the memory address of `num` (which holds a int) use `ptr1=# ptr2=ptr1` if you want ptr1 pointing to the memory address of k, and ptr2 pointing to the memory address of ptr1 (which holds a pointer to an int) then you need a pointer of pointer. So, despite how much memory it takes to store ints and *ints, they are different mammals, with different contents. – Anthony Accioly Jul 16 '13 at 15:19

7 Answers7

3

Simply put, pointers are not addresses, they are varibles representing an address with a type. So the types have be compatible for pointers to assign (with the exception of void * generic pointer).

ptr2 = &ptr1;

ptr1 has a type of int *, so &ptr1 has a type of int **, it's not the same with ptr2, which has a type of int *.

Reference: C99 6.5.16.1 Simple assignment

both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • Grammatically speaking,"ptr1 has a type of int *, so &ptr1 has a type of int **" seems to be reasonable,but from what I can see,at line ptr2 = &ptr1; ptr1 is just an variable(forget it is a pointer),and & operator feteches its address and then assign it to ptr2,there's no difference while I assignning an integer's address to ptr2,what differences under this two address – user2556058 Jul 16 '13 at 15:14
  • @user2556058 Right - the line `ptr2 = &ptr1`, given `int *ptr1, *ptr2;` should *not* compile, at least not without a big ugly warning... Sadly, some more permissive compilers aren't as diligent as they should be... – twalberg Jul 16 '13 at 15:16
  • @user2556058 Remember that every variable in C has a type, including pointer variables. So `&ptr1` is more than just an address, the compiler knows what type of variable this address holds. You'll need a cast to let the compiler think it's some other type. – Yu Hao Jul 16 '13 at 15:19
  • @YuHao we can also say that &ptr1 is a pointer,it is more than an address,but why pointer can not be assigned to another pointer,still don't understand – user2556058 Jul 16 '13 at 15:30
  • @user2556058 A pointer to `int` and a pointer to a pointer to `int` are two very different type. See the C99 standard I quote, for pointer assignment, there are some constraints to follow. Why not? Because C standard doesn't allow it. – Yu Hao Jul 16 '13 at 15:47
  • @YuHao I understand it ,pointer to pointer is different type from pointer to int,so it needs two different declaration – user2556058 Jul 16 '13 at 15:56
1

Yes you can assign a pointer's address to a pointer, but it must be a pointer to a pointer variable.

int **ptr3;
ptr3 = &ptr1;

The reason you can't assign it the way you were trying is that a pointer to an int is not the same as an int. Pointers must be pointing to the same type to be compatible. If you really know what you're doing you can explicitly cast it, but that's a path to danger.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • OP knows that, it's the last sentence in his question. – Carl Norum Jul 16 '13 at 15:01
  • @CarlNorum, I just noticed that. So I edited the answer to add a bit more, hope that helps. – Mark Ransom Jul 16 '13 at 15:02
  • I kind of understand it,pointer to int is one type,pointer to char is another type,so is pointer to pointer,it is another different type,when we need to store pointer to pointer type,the variable must be declared with "two asterisk" notation as we would "char asterisk" notation,because the pointer is pointing to different data type,am I right? – user2556058 Jul 16 '13 at 15:47
  • @user2556058, you almost have it - it's not just "pointer to pointer" it's "pointer to pointer to int", a "pointer to pointer to char" would be a different data type as well. – Mark Ransom Jul 16 '13 at 15:58
  • What is the return value of & operator,purely address or a pointer object that contains much more info like the length and something else? – user2556058 Jul 16 '13 at 16:06
  • @user2556058 the `&` operator creates a pointer. The value of the pointer is an address, but the type of the pointer is already known to the compiler and can be used to calculate the length for example. It isn't stored anywhere though. – Mark Ransom Jul 16 '13 at 16:28
  • @user2556058 The `&` operator has no "return value" in this context if you only see it as a normal function. In this context, where it's actually type algebra that's being used, `&` denotes an operation that maps an object (pointer to `int`) to another object (pointer to pointer to `int`) that the compiler then can use to calculate how to read or write to it. As a programmer, you see an address, but the compiler sees the typed object. – HonkyTonk Jul 16 '13 at 16:36
1

Your code is wrong. This expression:

ptr2 = &ptr1;

Attempts to make an int * out of an int ** without a cast. The C standard forbids such conversions without an explicit cast.

The reason it's not allowed is that pointer types aren't guaranteed by the standard to all be the same size - so the pointer to your pointer might not fit in the variable you declared to be a pointer to an int.

Since pointers to any type can be converted to and from void * implicitly, you could write (correct, but probably confusing) analogous code to that in your question:

int num = 45;
void *ptr1, *ptr2;
ptr1 = #
ptr2 = &ptr1;

But doing so will require you to carry around all of the type information in some other way:

printf("%d\n",*(int *)ptr1);
printf("%d\n",*(int **)ptr2);
Carl Norum
  • 219,201
  • 40
  • 422
  • 469
1

The short answer is that type matters; a pointer to int is a different, incompatible type from pointer to pointer to int. As others have mentioned, different pointer types may have different sizes and representations.

A pointer value is not just an address; it has additional type semantics. For example, the expression ptr++ will advance the pointer to the address of the next object of the base type. If the base type is char, then the pointer is advanced 1 byte. If the base type is int, the pointer is advanced sizeof (int) bytes.

John Bode
  • 119,563
  • 19
  • 122
  • 198
1

Simply put because it will confuse the compiler. The compiler can work only according to the language standard. It doesn't have a brain of its own.

The language standard tells the compiler that if there is a int *

go to the address stored in that variable and use it.

In case there is a int ** then it tells it

go to the address in that variable. You aren't done yet as that is also an address. Go there and use what is present there.

This goes on and on for int *** and so on.

Hope this helps you to get over this basic confusion.

Aseem Bansal
  • 6,722
  • 13
  • 46
  • 84
0

If you could assign any address to any pointer regardless of type, on the grounds that one address is just like any other address, consider the trouble you could get yourself into if the following became legal:

int n = 40;
int * p = &n;
int ** pp = &n;  /* Typeless address assignment as you would like */
printf("%d\n", **pp); /* Bad Things happen here */

or the other way round:

int n = 40;
int * p = &n;
int * p2 = &p; /* More typeless address assignment */
printf("%d\n", *p2); /* Definitely not what you want */

Even if one address was the same as any other, sensibly dereferencing a pointer would become somewhat troublesome if things worked the way you suggest.

The reason you can't do what you suggest is that the type information you'd lose under your proposal is needed for dereferencing to work. If all you wanted pointers to do was to store and retrieve addresses, you'd have a point, but they're not just used for this. If they were, we could just have void pointers and be done with it.

Crowman
  • 25,242
  • 5
  • 48
  • 56
0

I completely agree to your statement that when pointer variable always would store a value that is integer, as the address to any variable/array would be an integer.

But still the data-type that is used to declare the pointer is the one of whose address it would be storing.

There are 3 points:

 1. The bits that are used while storing integer values differ from machine to machine.
    i.e. 32-bit, 64-bit and further more complications may add-up.

 2. Memory occupied i.e. bytes of data stored in it. Reason is : somewhere even the pointer variable is stored in memory. Right?

 3. There are certain operations associated with pointers like ++ or --.

Remember, pointer type is dependent on the type of variable it points to. This is the reason/need for the pointer to pointer.