Вы назначаете указатель на сам указатель, а не на объект, на который ссылается.
int v = 10;
int *ptr = &v;
int **ptrptr = &ptr;
printf("%d\n", **ptrptr);
Итак, еще раз, почему бы не выбросить ошибку сегментации в ** ptr?
Случайно. Это UB, и ваш указатель имеет случайное значение. Это значение указывает на другое местоположение со случайным значением. Тогда вы разыменовываете этот второй. Так что, если эти случайные значения указывают на место в памяти, выделенное вашей программе, это не будет сбоем. Если нет, то это будет segfault.
Почему это печать 0
и 10
? Потому что в этом случае компилятор оптимизировал все операции с указателями из и предполагал, что неинициализированные указатели имеют значение NULL, просто печатая постоянные значения:
main:
push {r4, lr}
mov r1, #0
ldr r0, .L3
bl printf
mov r1, #10
ldr r0, .L3+4
bl printf
mov r0, #0
pop {r4, pc}
.L3:
.word .LC0
.word .LC1
.LC0:
.ascii "%x\012\000"
.LC1:
.ascii "%d\012\000"