Чтобы понять разницу, нам нужно понять два разных контекста .
- В значение контекстов имя массива типа
T
эквивалентно указателю на тип T
и равно указателю на первый элемент массива.
- В контекстах объекта имя массива типа
T
не сводится к указателю.
Что такое контекст объекта?
В a = b;
, a
находится в контексте объекта. Когда вы взяли адрес переменной, она используется в контексте объекта. Наконец, когда вы используете оператор sizeof
для переменной, он используется в контексте объекта. Во всех других случаях переменная используется в контексте значения.
Теперь, когда у нас есть это знание, когда мы делаем:
void f(int arr[4]);
Это точно эквивалентно
void f(int *arr);
Как вы узнали, мы можем опустить размер (4 выше) в объявлении функции. Это означает, что вы не можете знать размер массива, переданного в f()
. Позже, когда вы сделаете:
int a[]={1,2,3,4};
f(a);
В вызове функции имя a
находится в контексте значения, поэтому оно сводится к указателю до int
. Это хорошо, потому что f
ожидает указатель на int
, поэтому определение функции и использование совпадают. То, что передается в f()
, является указателем на первый элемент a
(&a[0]
).
В случае
int a[]={1,2,3,4};
int b[4] = a;
Имя b
используется в контексте объекта и не сводится к указателю. (Между прочим, a
здесь равно в контексте значения и сводится к указателю.)
Теперь int b[4];
назначает хранилище стоимостью 4 int
с и присваивает ему имя b
. a
было также назначено аналогичное хранилище. Таким образом, вышеприведенное назначение означает: «Я хочу сделать место хранения таким же, как и в предыдущем месте». Это не имеет смысла.
Если вы хотите скопировать содержимое a
в b
, то вы можете сделать:
#include <string.h>
int b[4];
memcpy(b, a, sizeof b);
Или, если вам нужен указатель b
, указывающий на a
:
int *b = a;
Здесь a
находится в контексте значения и сводится к указателю до int
, поэтому мы можем присвоить a
int *
.
Наконец, при инициализации массива , вы можете назначить ему явные значения:
int a[] = {1, 2, 3, 4};
Здесь a имеет 4 элемента с инициализацией 1, 2, 3 и 4. Вы также можете сделать:
int a[4] = {1, 2, 3, 4};
Если в списке меньше элементов, чем количество элементов в массиве, то остальные значения принимаются равными 0:
int a[4] = {1, 2};
устанавливает a[2]
и a[3]
в 0.