03_函数指针与指针运算

函数指针与指针运算

1. 多级指针

#include <stdio.h>

void update(int * i) { // 1000H内存地址
    // printf("update函数,i的内存地址是:%p\n", &i); // 2000H
    printf("update函数,i的内存地址是:%p\n", i); // 1000H
    * i = 999;
}

// 上节课同学问了我一个问题
// 其实是没有理解指针的意义(为什么main函数和update函数i的内存地址不一样?)
int mainT1() {
    int i = 100; // 1000H的内存地址
    update(&i);
    printf("main函数,i的内存地址是:%p\n", &i);
    return 0;
}
#include <stdio.h>
int mainT2(){
    int num = 999;
    // 一级指针 *
    // 在真实开发过程中,最多三级指针  int ***
    int * num_p = &num; // 取出num的内存地址给 num_p(一级指针)
    int ** num_pp = &num_p; // 取出num_p的内存地址给  num_pp(二级指针)
    int *** num_ppp = &num_pp;

    printf("num_p的值是:%p, num_pp的值是:%p\n", num_p, num_pp);
    // num_p的值是:0061FF18, num_pp的值是:0061FF14

    // 我先输出 999
    printf("二级指针获取最终的值:%d\n", **num_pp);
    printf("三级指针获取最终的值:%d\n", *** num_ppp);

    // printf("num_p的自己的内存地址是:%p, num_pp自己的内存地址是:%p\n", &num_p, &num_pp);
    // *num_ppp  取的是什么?

    return 0;
}

在这里插入图片描述

2. 数组与数组指针

#include <stdio.h>
int mainT3() {
    // 定义数组
    // int [] arr = {1,2,3,4}; 错误的写法
    int arr[]  = {1,2,3,4};

    // 遍历数组
    // 其他平台不能用 Clion能用, Linux上报错
    /*for (int i = 0; i < 4; ++i) {

    }*/

    // VS非常严格,规范,    CLion包容

    // Linux/Clion/Mac都没有问题
    int i = 0;
    for (i = 0; i < 4; ++i) {
        printf("%d\n", arr[i]); // 取值
    }

    // 数组 和 指针 挂钩
    // 数组的内存地址 == 第一个元素的内存地址  == &arr
    // 数组的内存地址 == 第一个元素,不是第二个元素,也不是第n个元素的内存地址
    printf("arr  =   %d\n", arr);
    printf("&arr  =   %d\n", &arr);
    printf("&arr[0]  =   %d\n", &arr[0]);

    // 既然数组就是一个内存地址
    int * arr_p = arr;
    printf("%d\n", *arr_p); // *arr_p 取出元素一内存地址的值 1
    arr_p ++; // 指针挪动   元素二的内存地址了
    printf("%d\n", *arr_p); // *arr_p 取出元素二内存地址的值 2
    arr_p += 2;
    printf("%d\n", *arr_p); // 输出4
    // 输出1
    arr_p -= 3; // 挪动指针指向到 元素一
    printf("%d\n", *arr_p);
    arr_p += 2000;
    printf("%d\n", *arr_p); // 系统值 572662306
    return 0;
}

在这里插入图片描述

3. 采用指针遍历数组

#include <stdio.h>
int mainT4() {
    // 定义数组
    // int [] arr = {1,2,3,4}; 错误的写法
    int arr[]  = {1,2,3,4};

    // 数组是连续的内存空间(没有断层,有规律) 数组  每次挪动 4个字节 == int数组
    int * arr_p = arr;

    int i = 0;
    for (i = 0; i < 4; ++i) {
        printf("位置%d的值是:%d\n", i, * (arr_p + i));
        // 04    08   12    16
        printf("位置%d的内存地址是:%p\n", i, (arr_p + i));
    }
    return 0;
}

4. 循环时给数组赋值

#include <stdio.h>
int mainT5() {
    // 定义数组
    int arr[4];

    int * arrP = arr;

    // sizeof arr == sizeof(arr)

    // 循环赋值操作
    int j = 0;
    for (j = 0; j < 4; ++j) {
        // 1.拿到 元素一 元素二 元素三 元素四 的内存地址   (arrP + j)
        // 2.取出 元素一 元素二 元素三 元素四 的内存地址 所对应的值 * (arrP + j)
        * (arrP + j) = (j + 10001);
    }

    // sizeof arr = 16
	// sizeof(int) = 4
    // 变量 刚刚赋值的数组
    for (int i = 0; i <  sizeof arr / sizeof(int); ++i) {
        printf("位置%d的值是:%d\n", i, * (arrP + i));
    }
    return 0;
}

5. 数组指针操作的几种方式

#include <stdio.h>
// 5.数组指针操作的几种方式。
int mainT6(){
    int arr[] = {1,9,0,9999};
    int * arrP = arr;
    for (int i = 0; i < sizeof arr / sizeof(int); ++i) {
        printf("%d\n", arrP[i]);
        // + i 挪动元素3内存地址 再取元素3内存地址所对应的值
        printf("---%d\n", *(arrP + i));
    }
}

6. 指针类型有何用?

#include <stdio.h>
int mainT7() {

    int num = 12;

    int * num_p = &num;

    // Clion优化处理,不报错; VS检测无法通过,会报错。
    double * num_p_d = num_p;

    printf("%d\n", sizeof num_p);
    printf("%d\n", sizeof num_p_d);

    // 指针占用的内存大小是?
    // int double xxx的指针 永远都是4个字节(32位编译器)或8个字节(64位编译器)

    // 6.指针类型有何用?。  既然都是 4个字节,为什么还要分 指针类型
    // 答:取值的时候,怎么取,这就是类型规定的好处

    // int * p; // 类型是为了计算偏移量

    char c = 'a';
    // char * p = &c;
    // char * p = "AAAA";

    return 0;
}

7. 函数指针

#include <stdio.h>
void add(int num1, int num2); // a.先声明
void mins(int num1, int num2) {
    printf("num1 - num2 = %d\n", (num1 - num2));
}

// 操作 回调到  add  mins
// void(*method)(int,int)  声明好 函数指针
// void 返回值
// (*method) 函数名
// (int,int) 两个参数
void opreate(void(*method)(int,int), int num1, int num2) {
    method(num1, num2);
    printf("opreate函数的 method指针是多少:%p\n", method);
}

// 函数指针。(回调)Java接口的回调
int mainT8() {  // 【第一种写法】

    opreate(add,  10, 10);
    opreate(mins,  100, 10);

    // 原理是什么?
    printf("main函数的 add指针是多少:%p\n", add);
    printf("main函数的 mins指针是多少:%p\n", mins);

    // &add和add是一样的值吗
    printf("%p, %p\n", add, &add); //  004018CE, 004018CE  一样的

    return 0;
}

// b.再实现 使用
void add(int num1, int num2) {
    printf("num1 + num2 = %d\n", (num1 + num2));
}

在这里插入图片描述

#include <stdio.h>

void callBackMethod(char * fileName, int current, int total) {
    printf("%s图片压缩的进度是:%d/%d\n", fileName, current, total);
}

// 压缩的方法
// 定义函数指针: 返回值(*名称)(int,double)
void compress(char * fileName, void(*callBackP)(char *,int,int)) {
    callBackP(fileName, 5, 100); // 回调给外交 压缩的进度情况
}

// 函数指针2
int main() {
    // 1 如果有问题
    // VS  Clion 通过了,  Linux 可能不通过(因为这样不合规范)
    // void (* call) (char *, int ,int) = callBackMethod;

    // 有种temp的思路一样的感觉
    //  2 再换成这种方式 【第二种写法】
    // Linux  先定义, 再赋值
    void (* call) (char *, int ,int);
    call = &callBackMethod;

    void (* call2) (char *, int ,int);
    void (* call3) (char *, int ,int);
    void (* call4) (char *, int ,int);
    void (* call5) (char *, int ,int);
    call5 = &callBackMethod; // &callBackMethod 1000H  == callBackMethod 1000H

    compress("derry.png", call5);

    // 常量指针  指针常量   【函数指针】

    // 字符串  操作符重载 + C函数
    // char * c = "Derry" + "A";
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

左绍骏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值