最近看ucos源代码,有好多和指针有关的地方看得稀里糊涂,重新翻了下C语言以及C++的书,把指针部分的知识梳理了一下:
◆ 计算机存储数据时必须跟踪的三种基本属性:
1. 信息存储在何处 (即地址,起始位置)
2. 存储的值为多少
3. 存储的信息是什么类型 (即占用多大的空间)
◆ 指针是一个变量,其存储的是值的地址,而不是值的本身
◆ 指针名表示的是地址。*操作符称为间接值或解除引用操作符,将其应用于指针,可以得到该地址处存储的值
◆ 指针声明必须指定指针所指向的数据类型,对于每个指针变量名,都需要使用一个*,例:
int *p1,p2; // 将创建一个指针(p1)和一个常规int变量(p2)
◆ 可以在声明语句中初始化指针。在这种情况下,初始化的是指针,而不是它所指向的值
int higgens = 5; int *pt = &higgens;
◆ 一定要在对指针进行解引用操作符(*)之前将指针初始化为一个确定的适当的地址
◆ 指针可保存0值,表面它不指向任何对象例:
1. int *pi = 0; // 指针不指向任何对象 2. if(!pi) // 判断指针是否指向对象 { ... } 3. OS_TCB *ptcb; ptcb = OSTCBFreeList; if(ptcb != (OS_TCB *)0) { ... }
◆ 不能简单地将整数赋给指针,要将数字值作为地址来用,应通过强制类型转换将数字转换,例:
int *pt; pt = (int *)0xB8000000;
◆ 将指针变量加1后,其增加的值等于指向的类型所占用的字节数
◆ const 修饰符,例:
const int *pt; // pt指向一个const int 型,因此不能用pt来修改这个值,即pt所指向的地址可以改变但不能通过*pt改变pt所指向地址的值 int sloth = 2; int * const finger = &sloth; // finger所指向的地址不能改变,但允许通过*finger修改该指针的地址里的值
◆ void* 指针
1. void* 指针表明该指针与一地址相关,但不清楚存储在此地址上的对象的类型,它可以保存任何对象的指针.
2. 该类型指针只支持以下几种操作:
a. 与另一个指针进行比较 (地址比较)
b. 向函数传递void* 指针或从函数返回void*指针
c. 给另一个void*指针赋值
3. 不能使用void*指针操纵它所指向的对象
4. 用途:该指针应该是用于只需要地址而不需要关心该地址存储的是何种类型的值,比如:如果函数的参数可以是任意类型的指针,
则应声明其参数为void* ,例如:
void * memcpy(void *dest, const void *src, size_t len); void * memset ( void * buffer, int c, size_t num );
◆ 函数指针
1.与数据相似,函数也有地址。函数的地址是存储其机器语言代码的内存的开始地址。函数名即能表示函数的地址,例如:
process(think); // 传递think()函数的地址给process() thought(think()); // 将think()函数的返回值传递给thought()
2. 声明指向函数的指针时,必须制定指针指向的函数类型。这意味着声明应指定函数的返回类型及函数的特征标(参数列表),即声明
应像函数原型那样指出有关函数的信息,例:
double pam(int); // 函数原型 double (*pf)(int); // 指针声明,(*pf)是函数,pf就是函数指针
要声明指向特定类型的函数的指针,可以先编写这种函数的原型,然后用(*pf)替换函数名,则pf即为函数指针
3. 赋值:函数指针只能通过同类型的函数或函数指针或0值常量表达式进行初始化,将函数指针初始化为0,表示该指针不指向任何函数
4. 使用指针来调用函数,有2种方式,例:
double pam(int); double (*pf)(int); pf = pam; (*pf)(5); // 法一 pf(5); // 法二