2015-07-08 1 views
-4
int main() 
{ 
    int a[4][2] = {1,2,3,4,5,6,7,8}; 
    printf("%d\n",*(a[2]+1)); 
    printf("%d\n", *(*(a + 2)+1)); 
    getch(); 
} 

Двумерный массив можно рассматривать как одномерный массив.
вывод этой программы - 6 в обоих printf. Мой вопрос заключается в том, как выполняется printf("%d\n", *(*(a + 2)+1)); и как приоритет оценки asterik * и +.Я застрял в этом коде доступа к значениям в 2D-массиве с помощью указателей

+2

Я считаю, что существует достаточно скобок, поэтому вам не следует путать с приоритетом. –

+0

, что приводит к 'a [2] [1]'. – Jarod42

+1

, если вы застряли с арифметикой указателя, просто не используйте его, но используйте простой 'a [2] [1]' вместо – user463035818

ответ

0

Давайте рассмотрим как ваши вызовы printf.

a[2] в клетке int[2] = {5,6}

a[2] + 1 является указателем, который держит адрес номер 6 (а [2] неявно преобразуется в указатель), так что после разыменования это 6.

a есть и int[4][2] массив, который преобразуется в указатель (после преобразования он держит указатель на первый элемент)

a + 2 является указателем, который держит адрес указателя на номер 5

*(a + 2) является указателем, который имеет адрес номер 5

*(a + 2) + 1 является указателем, который имеет адрес номер 6

*(*(a + 2) + 1) это номер 6

EDIT:

К сожалению, для некоторых неправильных утверждений. Я принимаю во внимание комментарии, и мне нужно добавить, что в приведенном выше примере выражение lvalue типа массива неявно преобразуется в указатель на его первый элемент.

+1

Фактически 'a [2]' и '* (a + 2)' оба являются указателями, которые содержат адрес массива типа 'int [2]', который содержит числа 5 и 6. Конечно, адрес массив совпадает с адресом первого номера, но тип отличается. Кроме того, 'a' как таковой не является указателем. Это массив. Однако, когда вы передаете 'a' в' + '-оператор, операнд * распаковывает * на указатель на первый элемент (который является массивом {1,2}, а не числом). – user2079303

+1

@ user2079303 a [2] и * (a + 2) не являются указателями. Это массивы. Но используемый в выражениях массив неявно преобразован в указатель на первый элемент tts. –

+0

'a [2]' - массив, который распадается на указатель. 'a [2] + 1' действительно является указателем, потому что' a [2] 'заглох. 'a' - это 2D-массив, который распадается на указатель на первый элемент (массив из двух целых чисел). 'a + 2' выполняет арифметику указателя на основе массива: возьмите' a', он распадается на указатель на массив из 2 int, поэтому увеличивайте адрес с помощью 2 * 2 * sizeof (int) = 16. Эта часть вашего ответа является неправильным и требует исправления. – Lundin

2

Если у Вас есть один одномерный массив как, например

int a[] = { 5, 6 }; 

то выражение a[1] эквивалентно выражению *(a + 1) и дает второй элемент массива, который равен 6.

Массив a из вашего примера

int a[4][2] = {1,2,3,4,5,6,7,8}; 

можно переписать следующим образом для ясности

int a[4][2] = { { 1,2 }, { 3,4 }, { 5,6 }, { 7,8 } }; 

Вы также можете ввести имя ЬурейеЕ для массива

typedef int T[2]; 

где наименование T обозначает тип int[2].

С помощью этого ЬурейеЕ вы можете переписать декларацию (инициализация может быть опущен) из исходного массива следующим образом

T a[4]; 

Теперь давайте рассмотрим выражение *(*(a + 2)+1). Подвыражение *(a + 2) эквивалентно a[2] и, как объяснялось выше, даст третий элемент массива типа T, где T имеет тип int[2]. Таким образом, объектом этого подвыражения будет, в свою очередь, один размерный массив типа T и соответствовать третьему элементу массива a. Мы можем представить его как

T tmp = { 5,6 }; 

или

int tmp[2] = { 5,6 }; 

Таким образом, выражение *(*(a + 2)+1) эквивалентно выражению *(tmp + 1), что эквивалентно tmp[1] и даст второй элемент этого массива мыслимые TMP. То есть вы получите 6.

+1

Если спросить, в какое время это было, я подозреваю, что вы пойдете в свойства кристаллов, пружин, кварца и т. Д., И закончите, сообщив мне, в какое время. – ryyker

+0

@ryyker Извините, я не понял ваш комментарий. Вы проголосовали за ответ? Что с этим не так? –

+0

@ryyker C - C. Вы должны понимать все грязные детали, чтобы безопасно использовать их. Это не язык высокого уровня, на котором вы можете просто вызвать 'for (me) {Write.Program (With2dArrays); } '. – Lundin

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