C笔记 指针

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();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值