2013-05-13 2 views
1

Просто, когда я расслабился, у меня есть ясное понимание указателей в контексте массивов, я упал лицом вниз по этой следующей программе. Я понял, как для массива arr, arr и &arr оба одинаковы по величине, но различны по типу, но я не могу получить твердую хватку над выходом следующей программы. Я пытаюсь визуализировать ее, но добиваюсь только частично. Я был бы признателен, если бы вы могли дать строгий и подробный объяснение этой вещи, чтобы такие ребята, как я, могли с этой путаницей навсегда.Для «int demo [4] [2]», почему все они одинаковы по величине: & demo [1], demo [1], demo + 1, * (demo + 1)? Что относительно типа?

В следующей программе, я использовал «2D» массив demo[][2] .Я знаю, что demo[] будет array of arrays размера 2.I также знаю, что demo используется только будет иметь тип (*)[2] .Still Я в недоумении о следующем:?

1) почему &demo[1] так же, как demo[1]demo[1] не должен быть адрес второго массива Что на земле &demo[1] тогда и почему его так же, как адрес второго массива ?

2) Я знаю, что второй printf() и четвёртый такой же, как и demo[1] не что иное, как *(demo+1) .Но я использовал его так, чтобы проиллюстрировать эту point.How она может быть равна третьей printf(), т.е. , как может демо + 1 быть равно * (демо + 1)? demo[1] такой же, как *(demo+1), хорошо известен, но как может demo+1 быть равным *(demo+1)? Как «что-то» может быть равно значению в этом «что-то»?

3) И так как это просто оказалось, я не очень умным, я должен остановить мою угадайку и спрашивать убедительный ответ о том, что является типы для следующего:

& демо [1]
демонстрационных [1]
демонстрационных +-

#include<stdio.h> 

int main(void) 
{ 
    int demo[4][2]= {{13,45},{83,34},{4,8},{234,934}}; 
    printf("%p\n",&demo[1]); 
    printf("%p\n",demo[1]); //Should have cast to (void*),but works still 
    printf("%p\n",demo+1); 
    printf("%p\n",*(demo+1)); 
} 

ВЫВОД:

0023FF28 
0023FF28 
0023FF28 
0023FF28 
+0

** Поиск ** * demo [1] дает 83, элемент 2-го массива. –

ответ

2

demo[1] является вторым элементом массива demo и является самим массивом. Как и любой другой массив, когда это не относится к оператору , он вычисляет указатель на его первый элемент - то есть demo[1] оценивает то же самое, что и &demo[1][0], адрес первого int в массиве demo[1] ,

&demo[1] является адресом массива demo[1], а так как адрес массива и адрес первого элемента этого массива являются обязательно то же самое место, &demo[1] равно &demo[1][0], которая равна голой demo[1]. Это ключевое понимание - первый элемент массива расположен в том же месте в памяти, что и сам массив, так же как первый член struct находится в том же месте в памяти, что и сама структура. Когда вы печатаете &demo[1] и demo[1], вы не печатаете указатель на массив и массив; вы печатаете указатель на массив и указатель на первый элемент этого массива.

demo+1 - адрес второго члена demo. *(demo+1) - это сам член (это массив demo[1]), но поскольку этот элемент является массивом, он вычисляет указатель на его первый член. Как и выше, его первый член обязательно совмещается с самим массивом. Дело не в том, что «что-то» равно значению «что-то», потому что, когда вы используете массив в таком выражении, он не оценивает сам массив.

  • &demo[1] является указателем на demo[1], который представляет собой массив из 2 int. Таким образом, его тип int (*)[2].
  • demo[1] представляет собой массив из 2 int. Его тип: int [2]. Однако при использовании в выражении, где это не относится к типу & или sizeof операторам, он будет вычислять указатель на его первый элемент, который является значением с типом int *.
  • demo+1 является указателем на demo[1] и его тип: int (*)[2].
+0

+1 действительно хорошо сформулированный ответ. Второе измерение и, следовательно, добавление * значения * эквивалентности «demo + 1», «demo [1]» и «& demo [1]», примечание второго из тех, которое в противном случае не было бы истинным в 1D-массиве, являются действительно хорошо выложен. Мне жаль, что я не смог бы снова проголосовать за вторую пулю в описаниях типов, в частности разницу между 'int (*) [2]' vs. 'int *' и почему. – WhozCraig

+0

@WhozCraig Мой старый приятель, пожалуйста, взгляните на этот, который ** caf ** ответил и оставил ваши полезные/полезные замечания там. http://stackoverflow.com/questions/16514806/for-a-structure-variable-why-is-the-initializer-21-19-3-6-same-as-21-19-3-6 –

+0

@ Rüppell Ответ svulture caf в этом вопросе одинаково твердый. Кажется, я вижу шаблон, образующий там = P. Я не думаю, что смогу ответить на него лучше. – WhozCraig

0

Подумайте о том, как массив выложена в памяти:

 
    +-----+-----+-----+-----+-----+-----+-----+-----+ 
    | 13 | 45 | 83 | 34 | 4 | 8 | 234 | 934 | 
    +-----+-----+-----+-----+-----+-----+-----+-----+ 
^  ^  ^  ^
    |   |   |   | 
demo[0]  demo[1]  demo[2]  demo[3] 

Тогда также помнить, что, естественно demo «точки» к первой записи в массиве. Из этого следует, что demo + 0, конечно, должен также указывать на первую запись, а другой способ получить адрес записи в массиве - с адресом-операндом &, который будет &demo[0]. Таким образом, demo равно demo + 0, что равно &demo[0].

Также помните, что для вашего примера каждая запись в demo - это еще один массив, а массивы и указатели в значительной степени взаимозаменяемы (поскольку массивы распадуются указателями).Из этого следует, что demo[0] может использоваться как указатель.

Теперь замените индекс 0 выше, с 1, и вы получили то же самое, что и наблюдаете.

+0

Можете ли вы также посмотреть на это: http://stackoverflow.com/questions/16514806/for-a-structure-variable-why-is-the-initializer-21-19-3-6-same-as-21 -19-3-6 ** caf ** уже взорвал его тяжелой артиллерией, но было бы еще лучше, если бы вы тоже смогли сделать несколько выстрелов в нее. Спасибо. –

0
     +-------+------+ 
         |  |  | 
         | 13 | 45 | 
        101 |  |  | 105 
         +--------------+ 
         |  |  | 
         | 83 | 34 | 
        109 |  |  | 113 
         +--------------+ 
         |  |  | 
         | 04 | 08 | 
        117 |  |  | 121 
         +--------------+ 
         |  |  | 
         | 234 | 934 | 
        125 |  |  | 129 
         +--------------+ 

Примечание: Предполагая sizeof(int) = 4

Предполагая 2D расположение (его не так, как в памяти, хотя, все они находятся в линии)

demo[i] является iй строка 2D-массива. которые сами являются 1D-массивами. demo[1] является 1th ряд. [Я имею в виду адрес с адресом 109].

&demo[1] 

является адрес demo[1] и является таким же, как базовый адрес этого row.Just как для 1D массивов. Имя массива дает адрес 1-го места. Здесь 1D имя массива demo[1]

demo[1] 

поскольку имена массивов также дают базовый адрес массива она является такой же, как &demo[1]

demo+1

demo является указателем и имеет значение 101. demo (т. Е. demo[0]) имеет тип 1 ряд [дрянное описание. Я имею в виду размер строки, имеющей два элемента: (*)[2]] Таким образом, demo+1 увеличивает его, указывая на следующую строку. Который сошедшие, как demo[1]

*(demo+1) 

demo+1 is the 1<sup>th</sup> row 

*(demo+1) и означает значение в этом месте. Это сам массив, поэтому он дает адрес. поскольку имена массивов дают адреса

+0

Я не знаю про остальную часть ответа, но я все еще смотрю на хорошее искусство ASCII !! –

+0

@ Rüppell'sVulture Нам всем нужно немного [помощь] (http://www.asciiflow.com/#Draw);): DI использовал [это] (http://www.asciiflow.com/#Draw) –

+0

Как люди это делают? Вручную? Должно быть, нужно много времени и усилий? Или доступны инструменты? –