Указатели на указатели в массивах - PullRequest
2 голосов
/ 04 ноября 2019

Привет, ребята. Я новичок в c ++, и у меня есть вопрос по поводу указателей и массивов. Я не уверен, что именно делает этот раздел кода. Как я вижу, iarray объявлен как обычный массив. Однако к q обращаются так же, как к массиву 2d.

    int iarray[10];
    int *p = iarray;
    int **q = &p;
    q[0][2] = 25;

И если я изменю значение iarray на:

    int iarray[10]{3,2};
    int *p = iarray;
    int **q = &p;
    q[0][2] = 25;

    cout << q[0][0] << endl;
    cout << q[1][0] << endl;

Первый из них выведет 3, что, как я понял, я объявилэто выше. Но второй пустой, и я не понимаю, почему.

Спасибо за любую помощь заранее. :)

Ответы [ 2 ]

2 голосов
/ 04 ноября 2019

Давайте посмотрим одну инструкцию за раз:

int iarray[10]; зарезервирует 10 байтов целого размера в памяти. Если sizeof(int) == 4, он зарезервирует 40 байтов. Давайте предположим, что диапазон памяти установлен в диапазоне от 0x10 до 0x37.

int *p = iarray резервирует 4 байта (если мы предположим, что мы работаем на 32-битном процессоре) и сохраняет начальный адрес в 40 байтах, зарезервированных впредыдущая инструкция. p - это сокращение, которое мы используем для ссылки на эти 4 байта. Допустим, эти 4 байта хранятся в 0x50 - 0x53.

int **q = &p резервирует еще 4 байта, которые будут содержать начальный адрес p (0x50). q может храниться в 0x60-0x63.

Оператор индекса массива в c ++ для указателей является сокращением для арифметики указателей. Например, q[N] - это то же самое, что и *(q + N), поэтому в моем примере q[0] даст вам значение по адресу 0x60-0x63, которое равно 0x50. Если вы снова используете оператор индекса, он будет применен к новому адресу (0x50), поэтому q[0][2] эквивалентно p[2], то есть iarray[2].

q[1] эквивалентно *(q + 1) = *(0x60 + 0x4) =*(0x64),Если вы посмотрите выше, мы никогда не резервируем адрес 0x64, поэтому мы читаем из памяти, которой мы не владеем - неопределенное поведение.

2 голосов
/ 04 ноября 2019

Давайте посмотрим на это:

int iarray[10]; // declare a array of 10 ints
int *p = iarray; // p is used like an alias for iarray, an int[] is also an int*
int **q = &p; //q is a pointer to pointer p

q указывает только на одно значение. Вы можете думать о q как о массиве с одной записью. Вы также можете написать это как int *q[] = { &p };

Так что q[1][0] - неопределенное поведение, так как q[1] уже выйдет за пределы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...