0

I was just trying something to understand pointer to pointer deeply. I write the code below

int x = 20;
int *p0 = &x;
int *p1 = &p0;
printf("*p0 = %d\n", *p0);
printf("**p1 = %d\n", *((int *)*p1));

I thought the output would be

*p0 = 20
**p1 = 20

As *p1 would be evaluated to the address of x as an integer value and then I could use casting to de-reference the value in address x. since the value of *p1 represents a valid memory location of x. But the output was

snapshot from xterm for output of the code

I would like to understand this behavior.

NOTE - this is purely academic, I have no intention to write code this way

Asaf Itach
  • 300
  • 6
  • 13
  • Is this C++ or C? – SuperStormer Jul 16 '22 at 19:35
  • 3
    `int *p1 = &p0;` should be `int **p1 = &p0;` Please check out compiler warnings. – Weather Vane Jul 16 '22 at 19:36
  • 1
    @WeatherVane his question was why it cause seg fault not how he should write the code – Asaf Itach Jul 16 '22 at 19:38
  • This is in C programming language – Mohammed Amer Jul 16 '22 at 19:38
  • @ Weather Vane I know this is the right way to write it but I ask to understand why this is not possible to understand how dereferenc operator work – Mohammed Amer Jul 16 '22 at 19:40
  • @AsafItach if the code does not compile - live - https://godbolt.org/z/6n1EPMv7x - how did it produce a segfault. WeatherVane's comment was to the point. – Richard Critten Jul 16 '22 at 19:41
  • @RichardCritten It generates 2 warning but it compiles and return 139 (segfault) – Mohammed Amer Jul 16 '22 at 19:47
  • Even if you `reinterpret_cast` here, it's likely that pointers are 64 bit and `int`s 32 bit on your system meaning you loose half of the info of the pointer because `int` is an intermediate type used. – fabian Jul 16 '22 at 19:47
  • Because `sizeof(int) != sizeof(int*)` and you loose the address: `warning: initialization of ‘int *’ from incompatible pointer type ‘int **’ ` – 273K Jul 16 '22 at 19:50
  • 1
    (1) If your program compiles with warnings, don't bother running it. Fix the warnings first. (2) A cast is an instruction to the compiler to shut up. Don't use casts unless you know your types better than the compiler does. – n. m. could be an AI Jul 16 '22 at 20:01
  • @MohammedAmer the segfault was a result of writing faulty code. If your car is squashed by a truck when you run a red light, it does not make much sense to examine what part of the truck caused damage. The solution is not to run the red light. – Weather Vane Jul 16 '22 at 20:15

2 Answers2

1

This line is not valid C or C++:

int *p1 = &p0;

The fact that you say you have compiled and run this code means that you have not turned on error checking in your compiler. You really must do that, otherwise you will write all kinds of code with undefined behavior which can crash or worse.

If you use GCC or Clang, run it with -Wall -Wextra -Werror. Then it will not compile your erroneous code.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
1

I think what you want to know is why this is happening:

let's say there are 3 boxes of memory

x y z
20 &x &y

why cant you do that *((int *) *z) => => *y => => x

and the answer is you should compile your code with warning flags and not write code like this!!

But, you can make it work by casting it as you want to treat it.

instead of

printf("**p1 = %d\n", *((int *)*p1));

you should write:

printf("**p1 = %d\n", *((int *)*((int **)p1)));

z is declared as int * so when you do this z - the compiler knows it's an int not an int so you can't take a 1-byte variable and treat it like it is a 4-byte variable

and for those who think it cant be compiled: enter image description here

Asaf Itach
  • 300
  • 6
  • 13