C语言_指针详解
0.闲话
看滴水逆向之后的学习总结。
编译环境:vc++6.0
个人认为:指针这一块要真正明白每个指针代表什么,如何在内存寻址,还是要看指针的反汇编,才能理解透彻。
1.内存引用
指针的更本就是对内存的引用,应为指针引用起来比较方便,但是,在此之前不许要明白,有些内存是不能引用的。
特别注意常量区。比如
char* p ="hello,world!\0"
此时的字符串helloworld就存储在常量区,通过指针p可以引用它,进行读操作,但是不能进行写操作,比如
*p = 'H;
这样写虽然能通过编译,但是程序不能运行,因为常量区的数据补课写入。
2.指针类型的实质及其大小。
包含char,short,int,double,这些变量类型的指针。
我下面以char型举例。
char* p;
这里的变量,并不是 * p,而是p,他的类型为 char*
(忘掉书上刻板的概念),也就是说,他在内存中和char型数据一样的存放变量,只不过char*
型数据存储的是地址。
可以发现,char*
的p和int
的a字节宽度都是4,只不过p的内存存储的是一个地址。
这样就更明显了,也就是说,
char* p;
这样只是代表一个数据类型为char*
的变量p,p在内存中的宽度为4,用于存放地址,而通过*p
,能寻找p存储的地址对应的数据,并且根据char*
,确定*p
的大小为char型,即1个字节。
通过上面的举例,我要说的是,所有的指针变量其实都是4个字节,因为他们用于存放地址。而通过*这个符号,可以引用对应地址的数据。
所以,二维指针,* * p,我们可以将p指向一个地址,这个地址存储的是另一个数据的地址,比如a的地址,那*p输出的就是a的地址, * *p输出的就是a的值。
三维指针,四位指针……等等就是这样反反复复寻找对应地址的数据。
3.指针寻址
既然不管指针什么类型,他的大小都是4个字节,且存储地址,那为啥还有划分类型呢?
不像数组的寻址,只需要str[i]中的i一直自增即可,而指针的寻址是根据数据偏移,而数据偏移的量,其实就跟这个指针的类型有关。比如
char* p;
int* q;
p++;
q++;
可以发下,char*
型的p自增,地址+1;而int*
型的q自增,地址+4;
所以当他指针寻址是,根据变量类型不同,偏移的量也不同。
4.结构体指针
结构体指针,一般用于指向一个结构体,方便查找数据。
strct student
{
char name;
int number;
int ave;
}stu;
//这个结构体的宽度为12,不是9,因为 存在字节对齐。
//结构体指针
struct student* p;
p = stu;
p++;
结构体指针同样以符合指针的寻址,偏移规则,
一般结构体引用变量的方式为
stu.number = 10;
而结构体指针p引用这个结构体stu的变量,方式为
p->number = 10;
5.数组指针
同结构体指针一样,数组指针一般指向一个数组的首地址。
举例一个char型的数组指针。
char (*p)[n] ;//一定要写(),不然性质就变了。
这里的变量名一样是p。而对于的数据类型是char (*)[]
调试一下
char (*)p[4];
因为char的大小为1个字节,所以p的大小为1*4=4。
如果是int
int (*)q[4];
因为int的大小为1,所以q的大小为4*4 = 4 。
而一维的数组指针的寻址,需要两个*,即
printf("%d",*(*(p+1)+1));
因为这p的大小为4,,所以*(p+1)的偏移为1 * 4,(因为是char型)。
而后面总共的偏移为1 * 4+1 * 1 = 5 ; 就相当于a[5],对应就是字符f。
6.指针数组
char *p[5];
指针数组的本质是一个数组,只不过数组的每个变量存放指针。
7.指针函数
指针函数的本质是一个函数,只不过函数的返回值为一个指针。
建议多写写
如果发现我写的有什么不对或者是写的不好的地方,欢迎大家留言交流。