指针就是指针,指针变量在 32位系统下,永远占 4 个byte ,其值为某一个内存的地址。指针可以指向任何地方,但是不是任何地方你都能通过这个指针变量访问到。
数组就是数组,其大小与元素的类型和个数有关。定义数组时必须指定其元素的类型和个数。数组可以存任何类型的数据,但不能存函数。
说起指针,就让我们想到数组。而数组和指针也是有区别的。指针,指的是描述一个变量的地址;我们可通过指针的偏移来指向下一个地址。数组,是描述相同元素的一个集合;数组名是常量地址,不可自加不可修改。
我们可以通过数组的下标访问或指针指针阶引用输出常量字符串。如:p[i] ,*(p+i)。
#include<stdio.h> int main() { int a[5] = { 1, 2, 3, 4, 5 }; int *ptr = (int *)(&a + 1); printf("%d,%d", *(a + 1), *(ptr - 1)); system("pause"); return 0; }
分析:
*(a+1)相当于a[0+1]=a[1]=2
&a不降级,指的是整个数组,ptr是整个数组再加上1,则指的是a[4]紧接着后面的1个地址。再减去1,则指针又指回去并对其阶引用,相当于a[4],a[4]=5。
#include<stdio.h> int main() { int a[4] = { 1, 2, 3, 4 }; int *ptr1 = (int *)(&a + 1); int *ptr2 = (int *)((int)a + 1); printf("%x,%x", ptr1[-1], *ptr2); system("pause"); return 0; }
分析:
&a不降级,是整个整型数组,+1,是整型数组4后的int大小的地址,ptr[-1]则通过下标方式对刚才的地址减去1后的地址,是4。
a代表数组首元素的地址,将它强制类型转换为int型,表示的是首元素的内容,为1,2
我根据sizeof分析数组与指针,如:
#include<stdio.h> int main() { int a[] = { 1, 2, 3, 4 }; printf("%d\n", sizeof(a));//16 printf("%d\n", sizeof(a + 0));//4 printf("%d\n", sizeof(*a));//4 printf("%d\n", sizeof(a + 1));//4 printf("%d\n", sizeof(a[1]));//4 printf("%d\n", sizeof(&a));//4 printf("%d\n", sizeof(&a + 1));//4 printf("%d\n", sizeof(&a[0]));//4 printf("%d\n", sizeof(&a[0] + 1));//4 system("pause"); int a[5]; int *p = &a;//?? int *q = a;//?? system("pause"); return 0; }
上面是通过数组的下标访问或指针指针阶引用输出常量字符串。
也许大家这时候会想,为什么只能是常量字符串呢,int型数组我就不可以了吗?这时候我们可以通过一个循环和指针阶引用去输出。
下面我将数组和指针就以下几点详细地区分(常考于笔试面试简答题中):
(1)指针常用于存放变化性的变量,而数组常常用于存放一种类型的不经常变动的数据。
(2)指针变量自身是,指针存放的是数据的地址,而指针变量本身的地址我们无从而知。而数组名代表的事我们常说的数组首元素的地址,而并非是数组的地址。要说是数组的地址的话,那我们就要对其数组名取地址了(不降级)。
(3)访问数据方式:指针常常是间接访问,我们先找到对应的地址,再通过阶引用或数组下标方式访问到数组。而数组可直接通过下标去寻找,即直接访问。
数组指针与指针数组,如int *p[10],[]优先级高于*,表示的是数组中的每个元素都是int*类型的。用画图表示的话,它是10个int型大小,每个int型中存放的是int*。而int(*q)[10]表示的是数组指针,归根结底,不管是什么指针,它都是指针,那么它就存放的是地址,只不过数组指针存放的是数组的指针。用画图表示的话,是地址,则是4个字节大小。这个指针指向了10个int型大小的数组。
接着,我想从传参和接收参数的角度分析数组和指针。
将一个一维数组、 一级指针传参时,可通过对实参做一份拷贝并传递给被调用的函数,无法把指针变量本身传递给一个函数:
my_print(arr1,len)
void my_print(int arr[],int len)或者
void my_print(int *arr,int len)
二维数组:
数组首元素传过去,用数组接收。
void my_print(int arr[][4],int len)
数组的列不能省略。
一级指针:
即对p2做一份拷贝,假设其拷贝名为_p2。那传递到函数内部的就是_p2 而并非p2本身。
二级指针:
int arr*[4];
test(arr);//数组指针的每一个元素都是的首元素传参
int test(int **q)//而数组指针存的是地址,需要用二级指针来存放地址的地址。