指针实际上就是变量的地址,例如:int a=4,p=&a,p存放的就是a变量的地址,printf("%p",p);打印的是第一个字节的地址(一个内存单元为一个字节,int类型占有个字节,占四个内存单元,打印p,打印的是小地址的内存单元)
指针的大小取决于地址所占据的内存空间,而地址所占据的内存空间取决于是32位还是64位的机器,若为32位的,则指针占4个字节,若为64位,则指针占8个字节。
1,指针类型决定了它决定了解引用时的权限(一次能操作几个字节)
例如:int a=0x11223344;char* p=&a;*p=0;
因为char*类型的指针只能访问一个字节,又因为a为整型变量,有4个字节,所以只改变四个字节中的一个字节的内容。
2,指针类型决定指针向前走或向后走的一步有多大。
因为p是char*类型的指针,所以p+1,只能往前走一个字节的内存单元,即改变的是a中第二个字节的数值。
3,利用指针打印数组
在数组中,int* p = arr;首先得到的是数组arr首元素的地址,p指针加1,可向后访问数组中的下一个元素(即第二个元素)。若p+2,则访问的是第三个元素。
指针减指针算出的是指针与指针间的元素个数(注意:两个指针所指的位为同一块空间,即同一个数组的不同元素的地址)
指针减指针可算出字符串的长度
可用来接收任意类型的地址,但不能直接进行指针的加减运算和解引用运算。
成因:1,野指针未初始化。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2,指针越界访问。 例如:int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = arr;? ? ? ? ? ? ? ? ? ? ? ?printf(“%d”,*(p+10))报错!因为p+10越界访问了? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?3,指针所指的空间被释放。例如:调用函数中会临时开辟空间给变量,当调用完毕时,临时创建的空间会被释放,若在函数中运用指针,函数调用后,该指针就不能使用了
NULL是C语言中的标识符常量,值为0,0也为地址,这个地址是无法使用的,对该地址进行读写都会报错。
printf("%d", *(p + i));==printf("%d", *(arr + i));==printf("%d", arr[i]);==printf("%d", p[i]);
一维数组传参时,传的是首元素地址,所以不能在函数中,计算数组个数int sz=sizeof(arr)/sizeof(arr[0]);因为在函数中sizeof(arr)arr首元素的地址,所以在32为机器下,sz=1;故应该在主函数中计算sz,并传参到函数中。
int a=1;int*p=&a;int**pp=&p;这时pp为二级指针。将a的地址储存在p中,再将p的地址放到pp中。int* *pp=&p;第二个*代表pp为一个指针,int*为p的类型。
p为指针,指针指向字符,故为字符指针。char*p=“abcde”;把字符的首元素地址放到p中,即p指向的是a的地址。我们可以将字符串想象成数组.? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 所以printf(“%c\n”,"abcde"[3]);==printf(“%c\n”,p[3]);
例题
补充:const的用法
int a=1;const int*p=&a;==int const *p=&a;这时const修饰*p,故a的值不能进行改变,即不能通过修改p指向的空间的内容,但p的值是不受限制的,故p=&b,是正确的。
int a=1;int*const p=&a;这时const修饰的是p变量,故p不能进行修改,故p=&b,是错误的。但*p不受const的限制,即可以通过修改p指向的空间的内容,即*p=2,语法是正确的。
在上述例题中,str1和str2分别表示str1数组和str2数组的首元素地址,所以str1!=str2,
而内容相同的字符串常量只能保存在一块内存中,所以str3和str4,这两个地址都指向字符串的首元素地址。所以str3==str4
int*p1[10]:p1是数组,数组里面有10个元素,每个元素的类型是整型指针
int (*p2)[10]:p2是指针,该指针指向数组,数组中有10个元素,每个元素是整型的
利用数组指针打印二维数组:
ine(*fp)(int,int)=&add;pf中存放的add函数的地址,add函数的两个参数是整形,返回类型为也为整型。
例题:void(*signal(int,void(*)(int)))(int)
signal是一个函数,它的参数有两个一个为整型,一个为函数指针,这个函数的参数为int型,返回类型为void。signal这个函数的返回类型为函数指针,这个函数的参数为int型,返回类型为void。
用typedef可将复杂的类型从命名,例如上述复杂的式子可简化为下面两个分式,
typedef? ? unit void(*)(int);
unit signal(int,unit)