C指针详解

2017-12-15 19:29:59来源:CSDN作者:u010318270人点击

分享
一、复杂的类型(1)int p;  // p是整型变量(2)int *p; // p是一个指针,指向的内容类型为int型(3)int p[3]; // p是一个数组,数组里的元素是int型(4)int *p[3]; // p是一个数组,数组里的元素是指针类型,指针所指向的内容类型为int型。[]优先级比*高(5)int (*p)[3]; // p是一个指针,指针所指向的内容是一个数组,数组里的元素是int型(6)int **p;  // p是一个指针,指针所指向的内容类型为指针,该指针指向的是int型(7)int p(int); // p是一个函数,形参是int,返回类型是int(8)int (*p)(int); // p是一个指针,指针指向的是一个函数,函数的形参是int,返回类型是int(9)int *(*p(int))[3]; // p是一个函数,形参为int,返回值是一个指针。返回的指针指向一个数组。数组里的元素是指针,指针指向的内容类型为int。二、指针的四个属性指针是一个特殊的变量,它里面存储的数值被解释为内存里的一个地址。要搞清一个指针,需要从四个方面入手:指针的类型、指针所指向的类型、指针的值(或叫指针所指向的内存区)、指针本身所占据的内存区。以下面几个指针作为例子,来说明指针的类型和指针所指向的类型。(1)指针的类型把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。(2)指针所指向的类型把指针声明语句里的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。(1)int *ptr;  //指针的类型:int *    //指针所指向的类型:int(2)char *ptr; //指针的类型:char *   //指针所指向的类型:char(3)int **ptr; //指针的类型:int **   //指针所指向的类型:int *(4)int (*ptr)[3]; //指针的类型:int (*)[3]   //指针所指向的类型:int ()[3](5)int *(*ptr)[4]; //指针的类型:int *(*)[4]   //指针所指向的类型:int *()[4](3)指针的值(指针所指向的内存区)    指针的值是指针本身存储的数值,这个值被编译器当作一个地址,而不是一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。   指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。(4)指针本身所占据的内存区    sizeof(指针的类型),32位平台里,指针本身占据了4个字节的长度。三、指针的算术运算指针可以加上或减去一个整数,相应指针的值需要加上或减去 整数*sizeof(指针所指向的类型)#include <stdio.h>
int main(){    char a[20] = "abcdefg ABCDEFG";   int *ptr = (int *)a;  //char *ptr = a;    ptr++;    printf("ptr:%c/n", *ptr); //result e    return 0;}指针ptr:指针的类型为int *,指针所指向的类型为int,把a强制类型转换赋值给ptr。指针ptr加1,编译器把指针ptr的值加上了sizeof(int),32位程序中,int占4个字节。由于地址是用字节做单位的,故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节。原本ptr指针的值为字符数组a的地址(即第0个元素a[0]的地址),向高地址方向增加4个字节,现在ptr指针的值为a[5]的地址。如果把指针类型改为char *,ptr++之后运行的结果为b。// 错误的程序,会造成core dump#include <stdio.h>int main(){    char a[20] = "abcdefg ABCDEFG";    char *p = a;    char **ptr = &p;    printf("**ptr:%c/n", **ptr);    ptr++;    printf("**ptr:%c/n", **ptr);    return 0;}ptr的指针类型为char **,指针指向的类型为char *。执行ptr++操作,指针会加上sizeof(char *),即ptr指针的值(*ptr)为&p+4,则**ptr(即*(&p+4))指向的值是未知的。四、运算符&和*&是取地址运算符,*是间接运算符。&a的运算结果是一个指针,指针的类型:a的类型加个*。指针所指向的类型:a的类型。指针的值:a的地址。*p的结果是p所指向的东西,它的类型是p指向的类型,它所占用的地址是p所指向的地址。int a = 12;int b;int *p;int **ptr;
p = &a;  //&a的结果是一个指针,指针类型是int *,指针指向的类型为int,指针指向的地址是a的地址*p = 24; //*p就是变量aptr = &p; //&p的结果是一个指针,指针类型是int **,指针指向的类型为int *,指针指向的地址是指针p的地址*ptr = &b; //&b的结果是一个指针,指针类型是int *,指针指向的类型为int。*ptr是一个指针,指针类型为int *,指针指向的类型为int。&b和*ptr的指针类型和指针指向的类型都一样,所以赋值没有问题。**ptr = 24; //*ptr是一个指针,指针指向的类型为int,所以**ptr是一个int类型。五、指针和数组的关系声明了一个数组TYPE array[n],则数组名array就有两重含义:第一,它代表整个数组,它的类型是TYPE [n];第二,它是一个常量指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也就是数组单元的类型。该指针的值就是数组第0号单元,指针本身占有单独的内存区,注意它和数组第0号单元占据的内存区是不同的。该指针的值是不能修改的,即类似array++的表达式是错误的。不同的表达式中数组名array可以扮演不同的角色。sizeof(array)中,array代表数组本身,故这时sizeof函数测出的是整个数组的大小sizeof(*array)测出的是数组单元的大小。表达式array+n中,array扮演的是指针,故array+n的结果是一个指针,它的类型是TYPE*,它指向的类型是TYPE,它指向数组第n号单元。sizeof(array+n)测出的是指针类型的大小,32位程序中结果是4。int array[10];int (*ptr)[10];ptr = &array;ptr是一个指针,它的类型是int (*)[10],它指向的类型是int[10]。sizeof(指针名称),返回的是指针自身类型的大小,4。sizeof(int (*)[10]) = 4sizeof(int [10]) = 40sizeof(ptr) = 4sizeof(*ptr) = 40六、指针和结构类型的关系struct MyStruct{    int a;    int b;    int c;};struct MyStruct ss = {20, 30, 40};struct MyStruct *ptr = &ss;int *p1 = (int *)&ss;通过指针ptr来访问ss的三个成员变量:ptr->a; // 或者使用(*ptr).a。ptr->b; ptr->c;通过指针p1来访问ss的三个成员变量:*p1;  //访问ss的成员a。*(p1+1);  //访问ss的成员b。【不能保证一定能访问到成员b】结构体中成员之间可能会有若干填充字节。*(p1+2);  //访问ss的成员c。【不能保证一定能访问到成员c】如果是数组的话没有问题,因为数组单元存放在连续的存储区里,单元与单元之间没有空隙。七、指针和函数的关系int fun(char *, int);int (*pFun)(char *, int);  // pFun是一个指针,指向的是一个函数,函数的形参是char *, int,返回类型是int型pFun = fun;int a = (*pFun)("abcdefg", 7); //通过函数指针调用函数八、指针的安全问题指针ptr是一个int *类型的指针,它指向的类型是int,它指向的地址是s的首地址。32位程序中,s占一个字节,int类型占四个字节。最后一条语句不但改变了s 所占的一个字节,还把和s 相临的高地址方向的三个字节也改变了。char s = 'a';int *ptr;ptr = (int *)&s;*ptr = 1234;在指针的强制类型转换时:ptrLeft = (TYPE *)ptrRight,如果sizeof(ptrLeft的类型) < sizeof(ptrRight的类型),那么使用指针ptrLeft访问ptrRight是安全的。否则是不安全的。
参考:http://blog.csdn.net/soonfly/article/details/51131141

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台