Что такое имя массива в c?

мне трудно понять тип и использование имени массива в C. Это может показаться длинным сообщением, но, пожалуйста, потерпите со мной.

Я понимаю, что следующее утверждение объявляет a тип int [] Я.е массива.

int a[30];

пока a также указывает на первый элемент массива и такие вещи, как *(a+2) действительны. Таким образом, делая a выглядеть указатель на целое число. Но на самом деле типы int [] и int* отличаются; в то время как первый является тип массива и позже указатель на целое число.

также переменная типа int [] преобразуется в переменную типа int* при передаче его в функции; как в C массивы передаются по ссылке (за исключением sizeof оператор).

здесь наступает момент, который заставляет меня мотаться. Взгляните на следующий фрагмент код:

int main()
{
    int (*p)[3];
    int a[3] = { 5, 4, 6 };

    p = &a;

    printf("a:%dt&a:%dn",a,&a);
    printf("%d",*(*p + 2));
}

выход:

a:2686720       &a:2686720
6

Итак, как работает приведенный выше код? У меня два вопроса:--20-->

  1. a и &a имеют те же значения. Почему?
  2. что именно int (*p)[3]; делать? Он объявляет указатель на массив, я знаю это. Но как это указатель на массив отличается от указатель на первый элемент массива и имя массив?

может ли кто-нибудь прояснить ситуацию? У меня чертовски много путаницы.

Я знаю, что я должен использовать %p в качестве заполнителя вместо использования %d для печати значения переменных указателя. Поскольку использование целочисленного заполнителя может печатать усеченные адреса. Но я просто хочу, чтобы все было просто.

6 ответов


  1. a и &A имеют одинаковые значения.Как?

они имеют одинаковое значение, но разные типы. Объекты массива не имеют заполнения между элементами (до или после), Поэтому адрес массива и адрес первого элемента массива одинаковы.

что есть:

(void *) a == (void *) &a
  1. что именно он делает int (*p)[3]; объявляет указатель на массив,я это знаю.Но,как указатель на массив отличается от указателя на первый элемент массива и имя массива?

это два разных типа указателей. Возьмем, например, арифметику указателя:

a + 1   /* address of the second element of the array */
&a + 1  /* address one past the last element of the array */

EDIT: из-за популярного спроса я добавил ниже некоторую информацию о преобразовании массивов.

за тремя исключениями, в выражении объект типа array of T преобразуется в значение указателя типа T указывая на первый элемент массива. Исключения, если объект является операндом sizeof или & унарный оператор или если объект является строковым литералом инициализация массива.

например это утверждение:

printf("a:%d\t&a:%d\n", a, &a);

фактически эквивалентно:

printf("a:%d\t&a:%d\n", &a[0], &a);

Также обратите внимание, что d спецификатор преобразования можно использовать только для печати целого числа со знаком; для печати значения указателя вы должны использовать p спецификатор (и аргумент должен быть void *). Поэтому для правильного использования:

printf("a:%p\t&a:%p\n", (void *) a, (void *) &a);

соответственно:

printf("a:%p\t&a:%p\n", (void *) &a[0], (void *) &a);

другие ответы уже объяснил проблему. Я пытаюсь объяснить это какой-то диаграммой. Надеюсь, это поможет.


при объявлении массива

int a[3] = {5, 4, 6}  

организация памяти выглядит так:

enter image description here

теперь отвечая на ваш вопрос:

  1. a и &a имеют одинаковые значения.Как?

как вы уже знаете, что a имеет тип массива и имя массива a становится указателем на первый элемент массива a (после распада),i.e указывает на адрес 0x100. Обратите внимание, что 0x100 также является начальным адресом блока памяти (array a). И вы должны знать, что, в общем, адрес первого байта называется адресом переменной. То есть, если переменная 100 байт, то ее адрес равен адресу первого байта.

&a - адрес всего блока памяти, i.e это адрес массива a. См. диаграмму:

enter image description here

теперь вы можете понять, почему a и &a оба имеют одинаковое значение адреса, хотя оба имеют разный тип.

что именно он делает int (*p)[3]; объявляется указатель на массив,я знаю это.Но,как указатель на массив отличается от указателя на первый элемент массива и имя массива?

см. приведенный выше рисунок, ясно объясняется, как указатель на массив отличается от указателя на элемент массива.
При назначении &a to p, потом p указывает на весь массив, имеющий начальный адрес 0x100.


Примечание: по линии

... как в C массивы передаются по ссылкам (за исключением


  1. a соответствует указателю, указывающему на 0-й элемент массива. В то время как то же самое происходит с &a.Он просто дает начальный адрес массива.

а,a --> pointer pointing to starting element of array a[],it does not know about other element's location..

&a --->address location for storing array a[] which stores first element location,but knows every element's location.

аналогично, расположение других элементов будет (a+2), (a+4) и так до конца массива.

следовательно,вы получили такой результат.

  1. int (*p)[3] - указатель на массив. если бы это было int * p[3], это означало бы совершенно разный. Это означало бы множество указателей, которые полностью отличались бы от этого контекста.

указатель на массив автоматически позаботится обо всех других элементы в массиве.В этом случае ваш is (p);

тогда как указатель на первый элемент массива, т. е. знаю только о первом элементе массива.Вам придется вручную дайте указателю арифметические направления для доступа к следующим элементам.Смотрите, в этот случай - - - мы можем получить второй элемент из a, добавив 2 к a, т. е. a+2, Третий элемент путем добавления 4 к a, т. е. a+4 и так далее. // виду разность двух, так как это целочисленный массив!


в ответ на вопрос 1, это просто аспект языка C, как разработан, в отличие от большинства других современных языков C/C++ позволяет напрямую манипулировать адресами в памяти и имеет встроенные средства, чтобы "понять", что. Есть много статей в интернете, которые объясняют это лучше, чем я мог бы в этом небольшом пространстве. Здесь один, и я уверен, что есть много других: http://www.cprogramming.com/tutorial/c/lesson8.html


с стандарт C99 n1124 6.3.2.1 p3

за исключением случаев, когда это операнд оператора sizeof или унарный & оператор или строковый литерал, используемый для инициализации массива выражение, имеющее тип " массив типа’, преобразуется в выражение с типом " указатель на тип’, указывающее на начальный элемент объекта array и не является lvalue. Если объект array имеет класс хранения register, поведение не определено.


a и &A имеют одинаковое значение, потому что давным-давно вы должны были использовать оператор адреса & на массивах, чтобы получить адрес массива, но это больше не нужно. Имя массива (в данном случае a) в эти дни просто представляет адрес памяти самого массива, который также является тем, что вы получаете от &a. Это стенография, которую компилятор обрабатывает для вас.