2015-03-12 4 views
2

Я знаю, что если arr - это массив, то arr[i]=*(arr+i); и если это 2D-массив, то arr[i][j]=*(*(arr+i)+j); Поэтому у меня есть этот кодЗачем мне нужен дополнительный астерикс с использованием 2D-массива?

main(){ 
    int arr[5][5]; 
    int arr2[25]; // same as arr[5][5]; 
    int i,j; 


    for(i=0;i<5;i++) 
     for(j=0;j<5;j++){ 
      arr[i][j]=i+j; 
      printf("arr[%d][%d] is at %p\n",i,j,&arr[i][j]); 
     } 

    printf("*(arr+i)=%d\n",*(arr+1)); // why this dont work 


    for(i=0;i<24;i++){ 
     arr2[i]=i; 
     printf("arr2[%d] is at %p\n",i,(arr2+i)); 
    } 

    printf("*(arr+i)=%d\n",*(arr2+1)); // prints 1 as expected 
} 

Я знаю, что в C нет такого понятия, как 2D массив, его в основном линейного ряд крупного смежного сгусток памяти. Поэтому мне интересно, почему я не могу напечатать значение 2D arr, используя * (arr + 1), что означает добавление 1*5*4 байт к базе arr и разыменование значения по этому адресу. Я знаю, что работает **(arr+1), но я не знаю, зачем мне эта дополнительная астерикс? Кроме того, если я делаю это printf("*(arr+i)=%p\n",*(arr+1)); так же, как я хотел бы использовать (arr+i) интерпретировать как адрес

+0

Что происходит с более волшебным зельем? – Quentin

+0

Есть ли у каждого с Обеликс? – Klors

+0

Какая черная магия? – BsD

ответ

3

arr - массив массивов int s. Его тип: int [5][5]. Таким образом, элементы arr являются 1D массивами. При использовании в выражении, в большинстве случаев, массивы преобразуются в указатель на свой первый элемент. В *(arr + 1), arr преобразуется в указатель на arr[0], т. Е. Первый массив 1D. Добавление 1 будет увеличивать его на 5*4 = 20 байт, т. Е. Следующий элемент массива arr, который равен arr[1].

С arr[1] это массив, его нельзя распечатать (в целом), но его адрес может быть. arr[1] сам по себе является массивом, и он будет распадаться на указатель на его первый элемент, то есть arr[1][0]. Чтобы распечатать свой элемент, вам понадобится другая разыменоваемость, которая получена arr[1][j] (j - это столбцы).

arr[1][j] эквивалентен *(arr[1] + j), что в конечном счете эквивалентно *(*(arr + 1) + j).

Рекомендуемая литература: What exactly is the array name in c?

+0

Так что в принципе 'arr [5] [5]' такой же, как 'arr [25]', когда используется в выражения 'arr [0]', 'arr [1]', 'arr [2]', 'arr [3]' и 'arr [4]' будут иметь тип 'int *'? – BsD

+0

@BsD; Ты можешь сказать. Но иногда управление памятью отличается в массивах 1D и 2D, содержащих равное количество элементов. – haccks

2

Тип *(arr+1) = тип arr[1] = int [5], который будет распадаться на int* при использовании в printf.

Для печати указателя, используйте:

printf("*(arr+i)=%p\n", *(arr+1)); 

Для печати объекта он указывает, использование:

printf("*(*(arr+i))=%d\n", *(*(arr+1))); 

Вы можете сделать легче читать ваш код с помощью:

printf("arr[1] = %p\n", arr[1]);  // Print the pointer 
printf("arr[1][0] = %d\n", arr[1][0]); // Print the value 
+1

Тип 'arr [1]' is 'int [5]'. – haccks

+1

Это намного понятнее, если вы пишете 'arr [1]' и 'arr [1] [0]' –

2

Как вы сказали, 2D-массив в C в основном представляет собой массив из 1D массивов. Вы можете подумать об этом как о массиве строк.

Самый правый * будет разыменовывать внешний массив, выбирая нужную строку.

*(arr+i)  //this gives me a pointer to the row I want 

* слева, который будет разыменованием во внутреннем массиве, выбрав элемент из строки.

*(*(arr+i)+j) //this gives me an element in the row 

**(arr+i) это всего лишь частный случай приведенного выше, где номер столбца j является 0.

Смежные вопросы