其实按照我的理解,数组和指针其实真没多大关系,指针是有真实内存的,里面的值为一个地址值,而数组是一块内存空间的名字
int a;
int *p = &a;
这两行代码的意思是
在栈上分配一个int 类型的空间,即4字节,命名为a;分配一个int *类型的空间,即8字节,命名为p。在p的内存中写入&a,即a的地址 。
而大多数人迷惑的原因在这
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int *p = a;
for (int i = 0; i < 10; i++) {
printf("%d %d %d %d\n", a[i], *(a+i), *(p +i), p[i]);
}
输出结果为:
0 0 0 0
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5
6 6 6 6
7 7 7 7
8 8 8 8
9 9 9 9
- 以指针的形式访问和以下标的形式访问数组
(1). 指针的形式:*(a + i)
。a
代表数组首元素的首地址,i
代表偏移sizeof(int) * i
.
(2). 以下标的形式:a[i]
。 编译器总是把下标的形式的操作解析成以指针的形式的操作。a[i]
会被解析成:a作为首元素的首地址,然后加上sizeof(int) *i. - 以指针的形式访问和以下标的形式访问指针
(1). 指针的形式:*(p + i)。先取出p存储的地址值。然后加偏移量
(2). 以下标的形式:p[i]。编译器总是把以下标形式的操作解析成以指针形式的操作。
以下标的形式访问的本质上在本质上与以指针的形式访问没有区别,只是写法上不同罢了
由上面的分析,指针和数组根本就是两个完全不一样的东西.只是他们都可以"以指针形式"或“以下标形式”进行访问。一个是完全匿名访问,一个是具名+匿名的形式访问。
char *p = "abcdefg";
char a[] = "123456";
- 第一句定义了一个指针变量p,p本身在栈上占8个byte,p里面存储的是一块内存的首地址。这块内存在静态区,其空间大小为7byte,这块内存也没有名字,完全是匿名的访问。
- 第二句定义了一个数组a,a拥有7个char类型的空间,其空间大小为7byte,数组a本身在栈上面。对a元素的访问必须先根据数组名字a找到数组首元素的首地址,然后根据偏移量找到相应的值。这是一种典型的“具名+匿名”访问。
数组与指针的对比
指针数组与数组指针
int *p1[10]; // 指针数组
int (*p2)[10]; // 数组指针
printf("%d\n", sizeof(p1));
printf("%d\n", sizeof(p2));
输出结果
80
8
- 指针数组:首先他是一个数组,数组的元素都是指针。
- 数组指针:首先他是一个指针,它指向一个数组。
注意:所有的测试结果在x86 -64位机,linux 4.15.0-29deepin-generic gcc 环境下测试