1 所有指针变量的大小(宽度)都是固定的
1.1 为什么指针变量的大小都是一样的?
因为存储空间所有字节的指针都是相同“宽度”的,
比如,如果地址宽度是32位的话,那么每个字节的地址都是32位的。
比如,如果地址宽度是64位的话,那么每个字节的地址都是64位的。
既然所有字节的指针宽度都是一样的,因此所有指针类型的宽度也都是一样的,
int * float * struct Student * double *
以上所有指针类型所规定的“宽度”是相同的,使用这些类型所定义的指针变量,其宽度也都是一样的。
指针变量是用来存放指针的,既然所有指针的宽度都是一样,那么存放指针的指针变量的宽度必然也是一样。
测试自己Linux和Windows下地址的宽度。
#include <stdio.h> int main(void) { int *p = NULL; printf("%d\n", sizeof(p)); //或者sizeof(int *)) return 0; }
我这边的情况:
1)windows
地址宽度为32位(4字节)。
2)Linux
地址宽度为64位(8字节)。
2 指针类型
1.1 指针的类型长什么样子
指针类型由基本类型 + *组成。
int * float * ...
1.2 定义指针变量
定义时,在指针类型*的后面加上变量名即可。
int *p; int **p;
1.3 指针类型中基本类型的作用
在前面就说过,int */struct student *等指针类型的宽度都是固定的,既然“宽度”固定的,那么指针类型中区分int、struct Student等基本类型有什么意义呢?
其实意义就在于,正是由于有int、struct Student等基本类型,所以对指针进行解引用时,才能正确的解释指针所指向的空间,比如:
int a = 100; int *p = &a; *p = 10000;
a的空间有4个字节,访问a的空间,只需要知道如下三件事:
(1)知道a第一个字节的地址,即a指针
(2)知道访问哪一个字节时结束
(3)知道空间的存储结构
*p解引用时,很显然是能够知道以上三件事的
(1)p中放的就是a指针
(2)int *中的基本类型为int,所以访问指针所指向的空间时,需要访问的空间大小为四个字节
(3)int *中的int也指明了,在访问指针所指向的空间时,按照整形的存储结构来解析的
总之对指针进行解引用时,指针类型中基本类型的作用,就是用于决定对所指向空间的解释方式。
指针类型都是固定宽度的,指针类型中的基本类型,与指针本身宽度无关,只与指针所指向空间的宽度有关。
1.4 对指针进行强制转换
前面说过=两边的类型必须一致,自然也包括指针类型。
(1)天然的一致
int a = 100; int *p = &a;
&a:a的指针,指针的数据类型为int *
p:指针变量,类型也为int *
(2)通过“强制转换”来保证类型一致
double a = 100.6; float *p = &a; //隐式强制转换 float *p = (float *)&a; //显式强制转换
(3)强制转换时做了什么
强制转换时,&a本身的值不改变,变的只是对指针所指向空间的“解释方式”。
double a = 100.6; float *p = (float *)&a; *p = 12.6;
&a:指针类型为double *
p:float *
两边的类型不一致,因此需要做强制转换。
直接使用&a访问所指向的空间时,
*(&a) = 200.02;
是按照double类型来解释的,但是将指针强制转换为float *后,再使用该指针去访问时,就会以float的类型去访问。
struct Student { int num; char name; float score; }; struct Teacher { char name; int num; }; struct Student stu = {123, "zhangsan", 87.6}; struct Teacher *stup = (struct Teacher *)&stu; //&stu为结构体指针,即第一个字节的地址
指针类型被强转为struct Teacher *后,通过stup解引用访问stu的空间时,则会以struct Teacher类型来解析。
指针(地址)就是一个数,至于这个数应该如何解释,就看这个数的类型,比如:
int a = 0;
· &a:为int *的指针,解引用时按照整形来解释&a所指向的空间。
· (int)&a:此时这个数就只是一个普通的整形数,此时不再是一个指针,不能进行解引用
· (void *)&a:为void *指针,这是一个空类型指针
空类型指针仅仅就是一个指针,不能被直接解引用,如果要解引用的话,必须将指针强制转换为int *、float *等具体指针类型,然后才能进行解引用,后面还会再次介绍void *。
· (struct student *)&a:结构体指针,解引用时会按照student student结构来解释。
a的合法空间只有4个字节,但是由于struct student类型大小>4个字节,所以按照struct student进行解引用访问时,所访问的空间会超过4个字节,这样会访问到其它的非法空间。
所以在实际编程中进行强制转换时,我们必须慎重使用强制转换。