1 变量p和*p的关系
void main(){
int i = 59;
int *p = &i;
printf("%#x,%ld\n",p,*p);
getchar();
}
打印结果为:
p存储的是i的地址,*P是取地址的值
2 不同的指针类型不能赋值
void main(){
int i = 59;
//int类型的指针
int *p = &i;
double j = 76.4;
//double类型的指针
p = &j;
//赋值为double类型变量的地址
//%#x是占位符 按十六位进制输出
printf("p的内存地址为:%#x,p的值为:%lf\n",p,*p);
getchar();
}
打印结果为:
该地址的值为:
可以看出地址上明明有值,值却为0。因为p为int类型的指针,不能赋给double类型的指针。
- int是四字节,double是8字节。四字节不能读取8字节的值。
- 指针有类型,地址没有类型。
- 地址是开始的位置,类型会表示读取到什么位置结束
3 空指针
void main(){
int i = 5;
int *p = NULL;
printf("%#x\n",p);//空指针的默认值为0
printf("%d\n",*p); //操作系统不允许访问内存地址0x00000000
getchar();
}
可以看到打印结果为0,并报如下异常
可能是系统占用的内存。不要给变量类型赋值为int类型的整数。操作系统不允许访问。
4 多级指针
void main(){
int i = 50;
int *p1 = &a;
int **p2 = &p1;
printf("p1:%#x\n",p1);
printf("p2:%#x\n",p2);
**p2 = 55;
printf("a的值为:%d\n",a);
getchar();
}
通过二级指针修改a,修改后a的值为55。
p2保存的是p1的内存地址,p1保存的是i的内存地址,i保存的是int类型的值
5 指针运算
void main(){
//数组在内存中连续存储
int ids[] = {34,53,45,87,14};
//数组变量名:ids就是数组的首地址
printf("%#x\n",ids);
printf("%#x\n", &ids);
printf("%#x\n", &ids[0]);
//指针变量
int *p = ids;
printf("p的值为:%d\n",*p);
//指针的加法
p++; //p++向前移动sizeof()个字节 移动对应的数据类型个字节
printf("p的值为:%d\n",*p);
getchar();
}
打印结果:
0x55f7e4
0x55f7e4
0x55f7e4
p的值为:34
p的值为:53
指针运算一般在数组遍历时用到,基于数组在内存中线性排列的方式。
6 通过指针给数组赋值
void main(){
int uids[6];
int *p = uids;
printf("%#x\n", p);
int i = 0;
for (; i < 6;i++){
uids[i] = i;
}
}
通过断点和p的内存地址,可以看到内存数组对应的值。
void main(){
int uids[6];
//早些版本的写法
int *p = uids;
printf("%#x\n",p);
int i = 0; //i是数组元素的值
for (; p < uids + 6; p++){
*p = i;
i++;
}
getchar();
}
7 函数指针
void msg(){
MessageBox(0,"消息内容","标题",0);
}
void main(){
msg();
}
运行结果:
使用函数指针:
void main(){
void(*fun_p)() = msg;
fun_p();
}
运行结果和上面的相同。
传参
void msg(char* msg,char* title){
MessageBox(0, msg, title, 0);
}
void main(){
//分三部分 1 函数的返回值类型 2 函数指针的名称 3 函数的参数列表
void(*fun_p)(char* msg, char* title) = msg;
fun_p("消息内容", "标题");
}
函数的内存地址
通过打印msg的内存地址
printf("%#x\n",msg);
可以找到内存地址对应的方法。
8 把函数作为参数,传递一个函数指针
//加法
int add(int a, int b){
return a + b;
}
//减法
int minus(int a, int b){
return a - b;
}
void caculate(int(*fun_c)(int a, int b), int m, int n){
int r = fun_c(m, n);
printf("%d\n", r);
}
void main(){
//相加
caculate(add, 10, 20);
//相减
caculate(minus, 40, 32);
getchar();
}
打印结果为30,8。
可以看出,在main()方法中,可以把add或者minus方法作为一个参数传递到caculate()方法中。
用随机数生成一个数组,写一个函数查找最小的值,并返回最小数的地址
int* getMinPointer(int ids[], int len){
int i = 0;
int*p = &ids[0];
for (; i < len; i++){
if (ids[i] < *p){
p = &ids[i];
}
}
return p;
}
void main(){
int ids[10];
//初始化随机数发生器,设置种子,种子不一样,随机数才不一样
//当前时间作为种子
srand((unsigned)time(NULL));
int i = 0;
for (; i < 10; i++){
ids[i] = rand() % 100;
printf("%d\n", ids[i]);
}
int *p = getMinPointer(ids,sizeof(ids)/sizeof(int));
printf("%#x,%d\n",p,*p);
getchar();
}