Адреса в языке Си

Программа 1

#include <stdio.h>

int main()
{
    int c = 12;
    
    int *a = &c + 11;
    
    printf("%d", *a);
    return 0;
}

Программа 2

#include <stdio.h>

int main()
{
    int *a;
    
    printf("%d", *a);
    return 0;
}

В первой программе выведется некоторое значение, во второй segfault. Так же первая программма упадет если отступить на большее число например &c + 11111

Вопрос

Как это грамотно объяснить? Буду признателен за подробный ответ

Изменено: я понимаю что это ub в обоих случаях, но мне все еще нужен более подробный ответ


Ответы (2 шт):

Автор решения: Harry

В обоих случаях вы ссылаетесь на память, не выделенную для использования программой.

В первом случае это память, отстоящая на 11 переменных int от c — но у вас ведь c не массив, так что это какая-то память в стеке.

Во втором a вообще имеет неопределенное значение, вы обращаетесь к памяти неизвестно где.

В любом случае и то, и другое — неопределенное поведение. А как именно себя проявит неопределенность — вопрос тоже неопределенный :)

→ Ссылка
Автор решения: user7860670

В обоих случаях проблемы случаются еще до обращения по кривым указателям.

В первом случае в выражении &c + 11 смещение имеет недопустимую величину. Когда адресная арифметика применяется к указателю на отдельный объект, то он рассматривается как массив из 1 элемента и прибавить к такому указателю можно либо 0, что не меняет значения указателя, либо 1, получив указатель на объект "следующий" за данным. Во втором случае полученный указатель может быть использован только для сравнения на равенство с исходным. Ну а смещение на 11 является Неопределенным Поведением, что (среди прочего) означает, что полученный указатель не обязательно будет указывать на память, отстоящую на 11 переменных int от c или вообще указывать куда-то на стек, как то утверждается в другом ответе.

Во втором случае происходит обращение к неинициализированной переменной a, что тоже является Неопределенным Поведением. Причем ещё до обращения к объекту, на который указывает указатель, именно чтение самого значения указателя.

→ Ссылка