Đây là ngôn ngữ chính xác từ các tiêu chuẩn C (n1256):
6.3.2.1 lvalues, mảng, và chức năng định danh
...
3 Trừ khi nó là toán hạng của
sizeof
toán tử hoặc toán tử
&
đơn nhất hoặc là chuỗi được sử dụng để khởi tạo mảng, biểu thức có loại '' mảng
loại '' được chuyển thành biểu thức có loại '' thành
loại ’Trỏ đến các yếu tố ban đầu của đối tượng mảng và không phải là một giá trị trái. Nếu đối tượng mảng có lớp lưu trữ đăng ký, hành vi là không xác định.
Điều quan trọng cần nhớ ở đây là có sự khác biệt giữa một đối tượng (về C, có nghĩa là một cái gì đó chiếm bộ nhớ) và biểu dùng để chỉ đối tượng đó.
Khi bạn khai báo một mảng như
int a[10];
các đối tượng định bởi biểu thức a
là một mảng (ví dụ:, một khối bộ nhớ liền kề đủ lớn để chứa 10 int
giá trị) và loại biểu thức a là "mảng 10 phần tử của int
" hoặc int [10]
. Nếu biểu thức biểu thịa
xuất hiện trong một ngữ cảnh khác với toán hạng của các toán tử sizeof
hoặc &
, thì loại của nó được chuyển đổi hoàn toàn thành int *
và giá trị của nó là địa chỉ của phần tử đầu tiên.
Trong trường hợp toán tử sizeof
, nếu toán hạng là biểu thức loại T [N]
, thì kết quả là số byte trong đối tượng mảng, không phải trong con trỏ đến đối tượng đó: N * sizeof T
.
Trong trường hợp của toán tử &
, giá trị là địa chỉ của mảng, tương tự như địa chỉ của phần tử đầu tiên của mảng, nhưng loại loại của biểu thức khác nhau: T a[N];
, loại biểu thức &a
là T (*)[N]
hoặc con trỏ đến phần tử N của T. Giá trị giống với a
hoặc &a[0]
(địa chỉ của mảng giống với địa chỉ của phần tử đầu tiên trong mảng), nhưng sự khác biệt trong các loại vấn đề. Ví dụ, với mã
int a[10];
int *p = a;
int (*ap)[10] = &a;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
p++;
ap++;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
bạn sẽ thấy đầu ra vào thứ tự của
p = 0xbff11e58, ap = 0xbff11e58
p = 0xbff11e5c, ap = 0xbff11e80
IOW, tiến p
thêm sizeof int
(4) với giá trị ban đầu, trong khi tiến ap
thêm 10 * sizeof int
(40).
Nhiều ngôn ngữ tiêu chuẩn:
6.5.2.1 subscripting Mảng
chế
1 Một trong những biểu thức có trách nhiệm gõ '' con trỏ đến đối tượng
loại '', khác biểu thức phải có loại số nguyên và kết quả có loại ''
loại ''.
Semantics
2 Một biểu thức postfix tiếp theo là một biểu hiện trong dấu ngoặc vuông
[]
là một định subscripted của một phần tử của một đối tượng mảng. Định nghĩa của toán tử số đăng ký
[]
là
E1[E2]
giống hệt với
(*((E1)+(E2)))
. Do quy tắc chuyển đổi áp dụng cho toán tử nhị phân
+
, nếu
E1
là đối tượng mảng (tương đương, con trỏ đến phần tử ban đầu của đối tượng mảng) và
E2
là số nguyên,
E1[E2]
chỉ định thành phần
E2
-th
E1
từ số không).
Vì vậy, khi bạn chỉ định một biểu thức mảng, điều xảy ra dưới mui xe là bù đắp từ địa chỉ của phần tử đầu tiên trong mảng được tính toán và kết quả sẽ bị hủy.Khái niệm
a[i] = 10;
tương đương với
*((a)+(i)) = 10;
tương đương với
*((i)+(a)) = 10;
tương đương với
i[a] = 10;
Vâng, mảng subscripting trong C là giao hoán; vì tình yêu của Thiên Chúa, không bao giờ làm điều này trong mã sản xuất.
Kể từ mảng subscripting được định nghĩa về hoạt động con trỏ, bạn có thể áp dụng các nhà điều hành subscript để biểu thức kiểu con trỏ cũng như kiểu mảng:
int *p = malloc(sizeof *p * 10);
int i;
for (i = 0; i < 10; i++)
p[i] = some_initial_value();
Dưới đây là một bảng tiện dụng để ghi nhớ một số các khái niệm:
Declaration: T a[N];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N] T * Address of the first element in a;
identical to writing &a[0]
&a T (*)[N] Address of the array; value is the same
as above, but the type is different
sizeof a size_t Number of bytes contained in the array
object (N * sizeof T)
*a T Value at a[0]
a[i] T Value at a[i]
&a[i] T * Address of a[i]
Declaration: T a[N][M];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N][M] T (*)[M] Address of the first subarray (&a[0])
&a T (*)[N][M] Address of the array (same value as
above, but different type)
sizeof a size_t Number of bytes contained in the
array object (N * M * sizeof T)
*a T [M] T * Value of a[0], which is the address
of the first element of the first subarray
(same as &a[0][0])
a[i] T [M] T * Value of a[i], which is the address
of the first element of the i'th subarray
&a[i] T (*)[M] Address of the i-th subarray; same value as
above, but different type
sizeof a[i] size_t Number of bytes contained in the i'th subarray
object (M * sizeof T)
*a[i] T Value of the first element of the i'th
subarray (a[i][0])
a[i][j] T Value at a[i][j]
&a[i][j] T * Address of a[i][j]
Declaration: T a[N][M][O];
Expression Type Converts to
---------- ---- -----------
a T [N][M][O] T (*)[M][O]
&a T (*)[N][M][O]
*a T [M][O] T (*)[O]
a[i] T [M][O] T (*)[O]
&a[i] T (*)[M][O]
*a[i] T [O] T *
a[i][j] T [O] T *
&a[i][j] T (*)[O]
*a[i][j] T
a[i][j][k] T
Từ đây, mẫu cho mảng chiều cao phải rõ ràng.
Vì vậy, tóm lại: mảng không phải là con trỏ. Trong hầu hết các ngữ cảnh, biểu thức mảng được chuyển đổi thành loại con trỏ.
có thể trùng lặp của câu hỏi từ C++ của trang web - faq: [Tên mảng có phải là con trỏ trong C?] (Http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in- c) –