Двумерные массивы и указатели - PullRequest
7 голосов
/ 29 декабря 2011

У меня есть следующий фрагмент кода:

char board[3][3] = {
                     {'1','2','3'},
                     {'4','5','6'},
                     {'7','8','9'}
                   };

printf("address of board : %p\n", &board);
printf("address of board[0] : %p\n", &board[0]);

Все операторы printf() выводят одно и то же значение: 0x0013ff67

  1. Насколько я знаюимя массива board (т.е.) представляет адрес первого подмассива (т.е.) board[0], а

  2. board[0] представляет адрес первого элемента в первом массиве (т. е.) board[0][0]

Почему я получаю один и тот же адрес во всех моих printf() утверждениях?Я ожидаю разные адреса для обоих утверждений.

Я довольно новичок в этом и не понимаю этого поведения.Пожалуйста, просветите меня.

Ответы [ 4 ]

5 голосов
/ 29 декабря 2011

Несмотря на то, что это двумерный массив, внутри памяти он будет представлен как линейный массив.поэтому, когда вы говорите, board [0] [0], он по-прежнему указывает на первый элемент в этом линейном массиве и, следовательно, на тот же адрес памяти.

1 голос
/ 29 декабря 2011

Возможно, вы знаете объектно-ориентированный язык, такой как Java или Python, и теперь вы изучаете язык Си. Разница между Java и C, если думать о char board[3][3], заключается в том, что в C переменная board представлена ​​в памяти как 9 символов по соседним адресам памяти. Вот так:

board: 1 2 3 4 5 6 7 8 9

В C &board дает тот же адрес памяти, что и &board[0] и &board[0][0].

В отличие от этого, в Java переменная будет объявлена ​​как char[][] board, и ее представление в памяти будет концептуально выглядеть следующим образом:

board: ptr(A) ptr(B) ptr(C)
A:     1 2 3
B:     4 5 6
C:     7 8 9

где ptr(x) указывает на адрес памяти x. Так, в Java board указывает на адрес памяти, отличный от board[0].


Вы говорите, что в C & board выдает тот же адрес памяти, что и & board [0] и & board [0] [0]. Но я могу получить доступ к первому элементу только через плату [0] [0] (или) * доска [0] (или) ** доска. Почему это так?

Хотя выражения &board и &board[0] и &board[0][0] дают один и тот же адрес, система типов языка C не позволяет вам получить доступ к значению char. В компиляторе C типы (концептуально):

board:       type char[3][3]
board[0]:    type char[3]
board[0][0]: type char

Предполагая переменную типа char, мы можем написать:

char c;
c = board[0][0];

но не могу написать:

char c;
c = board;    // Error
c = board[0]; // Error

, потому что тип на левой стороне несовместим с типом на правой стороне назначения.

Если вы уверены, что адрес указывает на char, вы можете использовать приведение типа:

char c;
c = *(char*)board;    // Works OK
c = *(char*)board[0]; // Works OK

Недостатком является то, что такие типы типов могут привести к ошибкам кодирования.

1 голос
/ 29 декабря 2011

Конечно, это напечатает тот же адрес.
Подумайте о 2D-массивах, как это, на минуту,

int ** ptr;


Адрес *ptr равен &(**ptr).

Поскольку в основном это то, что делает ваш код.

и помните, что в памяти двумерные массивы будут отображаться линейно.

1 голос
/ 29 декабря 2011

Насколько мне известно, имя массива board (т.е.) представляет адрес первой подмассивной (т.е.) платы [0]

Это верно только в случае использования boardвне этих контекстов

  • как операнд оператора &
  • как операнд sizeof

Когда применимо любое из этих выражений, выражение board представляет массив и продолжает иметь тип массива (char[3][3]).Применение к нему оператора & приводит к получению адреса массива, который, конечно, равен адресу его первого элемента, просто с другим типом (char(*)[3][3] вместо char(*)[3]).То же, что верно для массива board, верно и для его первого подмассива board[0].

Когда вы используете его вне этих контекстов, вы получаете адрес первого элемента (подрешетка в вашем случае).Этот адрес не объект, а просто значение.У значения нет адреса, а у объектов есть.Попытка применить & к нему потерпит неудачу.Например,

// error: trying to apply '&' on something that has no address
&(1 ? board : board)

Обратите внимание, что все сказанное выше относится к C;не обязательно до C ++.

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