美文网首页
12 C指针

12 C指针

作者: 亨锅锅 | 来源:发表于2018-10-30 13:07 被阅读0次

1、指针定义

#include <stdio.h>

int main()
{
    /*
     * 什么是地址?
     * 现实生活中   天津市城关镇长安路123号501
     * 在编程开发中  变量说占用内存空间的地址
     *
     * 地址有什么用?
     * 现实生活中, 我们是不是可以根据地址, 找到对应的房间
     * 在编程开发中, 也可以根据地址找到对应的内存空间
     *
     * 指针变量?
     * 指针变量和普通变量一样, 都是用来保存数据的
     * 只不过和普通变量有一点区别, 普通变量可以保存int/char/float/double等类型的数据
     * 指针变量只能保存内存地址
     * 简而言之, 指针变量, 就是专门用于保存内存地址的变量
     *
     * 定义指针变量的格式:
     * 数据类型 变量名称; // 定义一个普通变量
     * 数据类型 *变量名称; // 定义一个指针变量
     */

    int num;// 定义一个普通变量
    num = 9;

    // 注意点: 所有的指针变量占用的内存大小都一样
    // 在32位编译器中, 占用4个字节
    // 在64位编译器中, 占用8个字节
    int *p; // 定义一个指针变量
    // 将num变量的占用内存最小的那个地址存储到指针变量p中
    /*
     * 只要一个变量中存储了另外一个变量的内存地址, 那么我们就说这个变量指向了另外一个变量
     * 只要一个变量中存储了另外一个变量的内存地址, 那么我们就可以根据这个内存地址找到另外一个变量的内存
     * 从而操作那一块内存
     */
    p = &num;

    printf("&num = %p\n", &num); // &num = 0060FEA8
    // p和普通变量一样, 代表取出p中存储的值
    printf("p = %p\n", p); // p = 0060FEA8

//    printf("num = %i\n", num);
    // &p和普通&变量也一样, 代表取出p自己的内存地址
    printf("&p = %p\n", &p);

    return 0;
}

#include <stdio.h>

int main()
{
    // 1.定义一个普通变量
    int num;
    num = 6;
    // 2.定义一个指针变量
    int *p;
    // 3.利用指针变量, 保存某个变量的地址
    p = &num; // 将num的内存地址存储到了变量p中

    printf("修改之前: %i\n", num);
//    num = 8;
    *p = 4; // 在指针变量前面加上*号, 代表访问指针指向的那块内存
//    printf("修改之后: %i\n", num);
    printf("修改之后: %i\n", *p);
    /*
     * 只要一个变量保存了另外一个变量的地址, 就代表这个变量指向了另外一个变量
     * 只要一个变量指向了另外一个变量, 就可以通过*变量名称方式, 操作另外一个变量的内存空间
     */
    return 0;
}

#include <stdio.h>

int main()
{
    // 1.指针只能保存地址, 不能保存其它的值
//    int *p = 666; // 企业开发千万不要这样写
//    int *p = 3.14;  // 企业开发千万不要这样写
//    float num = 3.14;
//    int *p = &num; // 正确

    // 2.一个变量可以被多个指针指向
//    int num = 9;
//    int *p1;
//    int *p2;
//    p1 = &num;
//    p2 = &num;

////    *p1 = 668;
//    *p2 = 668;
//    printf("%i\n", *p1);
//    printf("%i\n", *p2);

    // 3.指针的指向可以改变
//    int num = 9;
//    int *p;
//    p = &num;
//    int value = 555;
//    p = &value;

//    printf("%i\n", *p); // 555

    // 4.定义指针变量时前面的数据类型, 必须和将来要保存的变量前面的数据类型一致
    int num = 6;
//    int *p;
    double *p;
    p = &num;

    return 0;
}

2、指针进阶

#include <stdio.h>

int main()
{
    /*
     * 指针为什么要有类型?
     * 由于指针变量指向的是某一个变量占用存储空间的首地址
     * 所以在获取指向变量中存储数据的时候, 指针是不知道要获取多少个字节的数据的
     * 所以指针变量的数据类型的作用, 就是告诉指针, 在获取指向变量的数据的时, 需要获取几个字节的数据
     *
     * 无论是什么类型的指针变量在相同的编译器下占用的内容都相同
     * 32位编译器下4个字节
     * 64位编译器下8个字节
     * int *p; // 代表告诉编译器, 将来获取p指向的那个变量的数据的时候, 需要获取4个字节的数据
     */
    /*
    int num;
    num = 6; // 0000 0000 0000 0000 0000 0000 0000 0110
    char ch;
    ch = 'a'; // 'a' --> ASCII码 --> 97 --> 0110 0001
    int *p;
    p = &ch;
    printf("*p = %i\n", *p);
    */

    int num;
    num = 666; //0000 0000 0000 0000 0000 0010 1001 1010
//    int *p;
    char *p;
    p = &num;
    // 1001 1010
    printf("*p = %i\n", *p); // int = 666, char = -102
    printf("%i\n", 0b10011010);
    return 0;
}

3、指针使用

#include <stdio.h>
//void change(int value);
void change(int *value);
int main()
{
    // 定义一个函数, 要求能够在函数中修改传入变量的值
    int num = 6;
    printf("调用之前:num = %i\n", num);
//    change(num);
    change(&num);
    printf("调用之后:num = %i\n", num);
    return 0;
}
//void change(int value){
// 结论: 如果函数的形参是数组或者是指针,
// 那么就可以在函数中修改外界传入变量的值
void change(int *value){ // 相当于 int *value = &num;
    *value = 888;
}

#include <stdio.h>
void swap(int *num1, int *num2);

int main()
{
    // 需求: 要定定义一个函数, 在函数中交换传入变量的值
    int a = 10;
    int b = 20;
    printf("a = %i, b = %i\n", a, b);
    swap(&a, &b);
    printf("a = %i, b = %i\n", a, b);
    return 0;
}
// 基本数据类型作为形参, 在函数内修改形参, 不会影响到函数外的实参
void swap(int *num1, int *num2){
    int temp = *num1;
    *num1 = *num2;
    *num2 = temp;
}
#include <stdio.h>
//int sum(int num1, int num2);
void test(int num1, int num2, int *res1, int *res2, int *res3, int *res4);
int main()
{
    // 需求: 要求定义一个函数, 可以同时返回两个变量的和,差,积,商
    // 需要大家知道的是: 在C语言中, 默认情况下一个函数只能返回一个值
    //                 如果想让某一个函数同时返回多个值, 可以借助指针来实现
    int a = 10;
    int b = 20;
//    int res = sum(a, b);
//    printf("res = %i\n", res);

    int d, e, f, g;
    test(a, b, &d, &e, &f, &g);
    printf("和 = %i\n", d);
    printf("差 = %i\n", e);
    printf("积 = %i\n", f);
    printf("商 = %i\n", g);
    return 0;
//    printf("return 后面的语句\n");
}

/**
 * @brief test 可以同时返回两个变量的和,差,积,商
 * @param num1 参与运算的第一个变量
 * @param num2 参与运算的第二个变量
 * @param res1 和
 * @param res2 差
 * @param res3 积
 * @param res4 商
 */
void test(int num1, int num2, int *res1, int *res2, int *res3, int *res4){
    *res1 = num1 + num2;
    *res2 = num1 - num2;
    *res3 = num1 * num2;
    *res4 = num1 / num2;
}

/*
int sum(int num1, int num2){
    // 注意点:
    // return的作用是用于结束当前函数
    // 只要函数执行到return, 就会立刻停止往下执行
    // 所以return 后面不可以编写任何语句, 因为执行不到
    return num1 + num2;
//    return num1 - num2;
//    return num1 * num2;
//    return num1 / num2;
}
*/

4、多级指针


#include <stdio.h>

int main()
{
    /*
     * 前面我们学习的指针我们称之为一级指针
     * 什么是多级指针
     * 指针中保存的又是其它指针的地址, 我们就称之为多级指针
     * 如何定义多级指针
     * 在要保存的指针变量的基础上加一颗星即可
     * 例如: int *p;  如果想保持指针变量p的地址, 只需在定义时多加一颗星即可 int **pp;
     *
     * 访问的规则:pp
     * 如果定义就如何范围, 例如: int *p; 访问 *p;  例如: int **pp; 访问 **pp;
     *
     * 定义指针的规律:
     * 1.将要指向的变量的定义拷贝过来
     * 2.再拷贝过来的代码的类型和变量名称中间加上一颗星
     * 3.修改变量名称
     */

    int num;
    num = 6;

    // 一级指针
    int *p;
    p = &num;
    printf("*p = %i\n", *p); // 6


    // 取出变量num的地址
//    printf("&num = %p\n", &num); // &num =  0060FEAC
    // 取出p中存储的地址
//    printf("p = %p\n", p); // p =  0060FEAC
//    printf("&p = %p\n", &p); // &p = 0060FEA8


    // 二级指针
    int **pp;
    pp = &p;
//    printf("&pp = %p\n", &pp); // &pp = 0060FEA4
    // 结论: *pp == p == &num;
//    printf("*pp = %p\n", *pp); // *pp = 0060FEAC

    //   *(*pp)  --> *(p) --> *p --> num
    // 规律: 如果想通过多级指针获取某个变量的值, 那么是几级指针, 前面就写几颗星即可
    // 注意点: 在企业开发中, 最多二级指针, 三级顶天了, 四级没见过
    printf("**pp = %i\n", **pp);

    // 三级指针
    int ***ppp;
    ppp = &pp;
    printf("***pp = %i\n", ***ppp);

    return 0;
}

4、指针和数组

#include <stdio.h>

int main()
{
    /*
     * 指针和数组
     */
    int ages[3] = {1, 3, 5};

    for(int i = 0; i < 3; i++){
        printf("ages[%i] = %i\n", i, ages[i]);
    }

    // 数组名称保存的就是数组占用内存最小的那个地址
//    printf("ages = %p\n", ages); // ages = 0060FEA0
//    printf("&ages = %p\n", &ages); // ages = 0060FEA0

    // 既然数组名称保存的就是地址, 而指针也是用于保存地址的, 所以指针也可以指向数组
    int *p = &ages;
//    printf("p = %p\n", p); // 0060FEA0
    // 结论: 如果利用指针保存数组的地址之后, 那么 p = ages = &ages;

    // ages[0] 相当于 0060FEA0[0]
//    ages[0] = 8;
//    p[0] = 999;


    printf("--------------\n");
    for(int i = 0; i < 3; i++){
        printf("p[%i] = %i\n", i, p[i]);
    }
    return 0;
}
#include <stdio.h>

int main()
{
    /*
    // 要求你写出三种访问数组元素的写法
    int ages[3] = {1, 3, 5};
//    printf("ages[0] = %i\n", ages[0]);
    int *p = ages;
//      printf("p[0] = %i\n", p[0]);
      printf("0[p] = %i\n", 0[p]);
      */

    /*
     * 指针可以进行加减法
     * 指针 +1  -1
     * 应用场景: 一般都是用在指针数组中
     *
     * 指针变量+1是加多少, 加的就是指针变量类型占用的字节数
     * 注意点:
     * 1. -1操作一般企业开发不会用到
     * 2.只有指针才可以做+1-1操作, 数组名不可以
     */

    int ages[3] = {1, 3, 5};
    int *p = ages;
//    printf("*p = %i\n", *p); // 1
//    printf("*(p + 1) = %i\n", *(p + 1)); // 3
//    printf("*(p + 2) = %i\n", *(p + 2)); // 5

//    printf("*p = %i\n", *p++); // 1
//    printf("*p = %i\n", *p++); // 3
//    printf("*p = %i\n", *p); // 5
//    printf("*p = %i\n", *(--p)); // 3


    for(int i = 0; i < 3; i++){
//        printf("ages[%i] = %i\n", i, ages[i]);
        printf("ages[%i] = %i\n", i, *p++);
    }
    return 0;
}

5、指针和字符串


#include <stdio.h>

int main()
{
    /*
     * 指针和字符串
     * 字符串的本质就是数组, 所以指针也可以指向字符串
     * 正式因为如此, 所以定义字符串又多了一种方式
     */

    // 字符串
//    char str1[] = {'m', 's', 'h', '\0'};
//    char str2[] = "msh";
//    char *str4 = "msh";
//    printf("str1 = %s\n", str1);
//    printf("str2 = %s\n", str2);
//    printf("str4 = %s\n", str4);


//    char *str3 = {'m', 's', 'h', '\0'};
//    printf("str3 = %s\n", str3);

    /*
     * 利用数组和指针定义字符串的区别:
     * 1. 存储的位置不同
     * 如果是通过数组定义的字符串, 那么存储在内存的栈中
     * 如果是通过指针定义的字符串, 那么存储在内存的常量区中
     *
     * 2.由于在内存中存储的位置不一样, 所以特性也不一样
     * 如果是通过数组定义的字符串, 我们是可以手动修改
     * 如果是通过指针定义的字符串, 我们不用手动修改
     *
     * 3.由于在内存中存储的位置不一样, 所以特性也不一样
     * 如果是通过数组定义的字符串, 每次定义都会重新开辟存储空间
     * 如果是通过指针定义的字符串, 重复定义不会重新开辟存储空间
     */

//    char str[] = "lnj";
//    char *str = "lnj";
//    printf("str = %s\n", str);
//    str2[1] = 'T';
//    printf("str = %s\n", str);


//    char str1[] = "lnj";
//    char str2[] = "lnj";
//    printf("str1 = %p\n", str1); // 地址不一样
//    printf("str2 = %p\n", str2);

    char *str1 = "lnj";
    char *str2 = "lnj";
    printf("str1 = %p\n", str1); // 地址一样
    printf("str2 = %p\n", str2);

    return 0;
}
#include <stdio.h>
//void test(int nums[]);
void test(int *nums);
char* demo();

int main()
{
    /*
     * 1.接收字符串的时候, 只能通过字符数组, 不能通过字符指针
     * 2.如果函数中返回的字符串是通过数组创建的, 那么外界无法获取
     *   如果函数中返回的字符串是通过指针创建的, 那么外界可以获取
     */
//    char str[10];
//    char *str;
//    scanf("%s", str);
//    printf("str = %s\n", str);

//    int ages[3] = {1, 3, 5};
//    test(ages);
//    printf("ages[1] = %i\n", ages[1]);

    char *res = demo();
    printf("res = %s\n", res);

    return 0;
}

char* demo(){
//    char str[] = "msh";
    char *str = "msh";
    return str;
}


// 注意点: 学习了指针之后, 建议将过去形参的数组类型修改为指针类型
//void test(int nums[]){
//void test(int *nums){
//    nums[1] = 6;
//}
#include <stdio.h>

int main()
{
    // 字符串数组
    // 字符串就是一个数组, 所以字符串数组就是一个二维数组

//    char str1[] = "msh";
//    char str2[] = "abc";
//    char str3[] = "def";

//    char str[][] = {
//        "msh",
//        "abc",
//        "def"
//    };

    char *str1 = "msh";
    char *str2 = "abc";
    char *str3 = "def";
//    char *str[] = {
//        str1,
//        str2,
//        str3
//    };

    // 字符串数组的第二种格式
    char *str[] = {
        "msh",
        "abc",
        "def"
    };

    return 0;
}
#include <stdio.h>

int main()
{
    /*
     * 变量的共同特点:
     * 1.可以用来保存数据
     * 2.可以用来当做形参
     * 3.可以用来当做返回值
     *
     * 所以指针变量也是一个变量, 所以指针变量也可以用于
     * 1.可以用来保存数据
     * 2.可以用来当做形参
     * 3.可以用来当做返回值
     */

    int num;
    num = 9; // 保存数据

    test(num);
    return 0;
}

void test(int value){ // 当做形参
    printf("value = %i\n", value);
}

int demo(){
    int temp = 998;
    return temp; // 当做返回值
}
#include <stdio.h>
#include <string.h>

int myStrlen(char *str);

int main()
{
    /*
     * strlen();
     * strcat();
     * strcpy();
     * strcmp();
     */

    char *str = "yl888";
//    char str[10] = {'m', 's', 'h', '\0'};
    // 注意点: strlen计算的是保存了多少个字符串
    // 计算规则, 就是返回字符串中\0之前有多少个字符
//    int res = strlen(str);

    int res = myStrlen(str);
    printf("res = %i\n", res);
    return 0;
}


int myStrlen(char *str){
    // 1.定义变量记录当前有多少个
    int count = 0;
    while(*str++){
        count++;
    }

//    while(*str++ != '\0'){
//        count++;
//    }

//    while(str[count] != '\0'){
//        count++;
//    }
    return count;
}
#include <stdio.h>
#include <string.h>
void myStrcat(char *str1, char *str2);
int main()
{
    /*
     * strlen();
     * strcat();
     * strcpy();
     * strcmp();
     */
//    char *str1 = "msh";  // 不能用于拼接
//    char *str2 = "yl888";
    char str1[10] = "msh";
    char str2[10] = "888";
//    strcat(str1, str2);
    myStrcat(str1, str2);
    printf("str1 = %s\n", str1);
    return 0;
}

void myStrcat(char *str1, char *str2){
//    while(*str1){
//         str1++;
//    }
    while(*str1++);
    str1--;

    while(*str2){
        *str1 = *str2;
        str1++;
        str2++;
    }

    /*
    // 1.拿到第一个数组\0的位置
    int index = 0;
    while(str1[index] != '\0'){
        index++;
    }
    // 2.将第二个数组添加到第一个数组末尾
    int count = 0;
    while(str2[count] != '\0'){
        str1[index] = str2[count];
        count++;
        index++;
    }
    */

}
#include <stdio.h>
#include <string.h>

int myStrlen(char *str);

int main()
{
    /*
     * strlen();
     * strcat();
     * strcpy();
     * strcmp();
     */

    char *str = "msh";
//    char str[10] = {'m', 's', 'h', '\0'};
    // 注意点: strlen计算的是保存了多少个字符串
    // 计算规则, 就是返回字符串中\0之前有多少个字符
//    int res = strlen(str);

    int res = myStrlen(str);
    printf("res = %i\n", res);
    return 0;
}


int myStrlen(char *str){
    char *startP = str;
    while(*str++);
    str--;
    return str - startP;


    // 1.定义变量记录当前有多少个
//    int count = 0;
//    while(*str++){
//        count++;
//    }

//    while(*str++ != '\0'){
//        count++;
//    }

//    while(str[count] != '\0'){
//        count++;
//    }
//    return count;
}
#include <stdio.h>
#include <string.h>
void myStrcat(char *str1, char *str2);

int main()
{
    // strcat
    // 注意点: 第一个参数必须足够大
    char str1[9] = "msh";
    char str2[10] = "yl888";
//    strcat(str1, str2);
    myStrcat(str1, str2);
    printf("str1 = %s\n", str1);
    return 0;
}
void myStrcat(char *str1, char *str2){
    // 1.将指针移动到第一个字符串\0的位置
//    while(*str1 != '\0'){
    while(*str1){
        str1++;
    }
    // 2.依次取出第二个字符串的每一个字符串, 添加到第一个字符串的后面
//    while(*str2 !='\0'){
    while(*str2){
        *str1 = *str2;
        str1++;
        str2++;
    }
    *str1 = '\0';
}
/*
void myStrcat(char *str1, char *str2){
    // 1.定义变量记录第一个字符串\0的位置
    int index = 0;
    // 2.通过循环找到第一个字符串\0的位置
    while(str1[index] != '\0'){
        index++;
    }
    // 3.定义变量记录第二个字符串的索引
    int i = 0;
    // 4.通过循环取出第二个字符串中的每一个字符串, 放到第一个字符串后面
    while(str2[i] != '\0'){
        str1[index] = str2[i];
        index++;
        i++;
    }
//    printf("index = %i\n", index);
    str1[index] = '\0';
}
*/

#include <stdio.h>
#include <string.h>
void myStrcpy(char *str1, char *str2);
int main()
{
    // strcpy
    char str1[9] = "msh";
    char str2[10] = "ly";
//    strcpy(str1, str2);
    myStrcpy(str1, str2);
    printf("str1 = %s\n", str1);
    return 0;
}
void myStrcpy(char *str1, char *str2){
    while(*str2){
        *str1 = *str2;
        str1++;
        str2++;
    }
    *str1 = '\0';
}
/*
void myStrcpy(char *str1, char *str2){
    int index = 0;
    while(str2[index] != '\0'){
        str1[index] = str2[index];
        index++;
    }
    str1[index] = '\0';
}
*/
#include <stdio.h>
#include <string.h>
int myStrcmp(char *str1, char *str2);

int main()
{
    // strcmp
    char str1[9] = "125";
    char str2[10] = "124";
    // 两个字符串相同返回0
    // 第一个参数小于第二个参数 -1 负数
    // 第一个参数大于第二个参数 1 正数
    // 如果前面的内容都相同, 第一个参数的个数小于第二个参数, -1 负数
    // 如果前面的内容都相同, 第一个参数的个数大于第二个参数, 1 正数
//    int res = strcmp(str1, str2);
    int res = myStrcmp(str1, str2);
    printf("res = %i\n", res);
    return 0;
}
int myStrcmp(char *str1, char *str2){

//    while(*str1 != '\0' || *str2 != '\0'){
     while(*str1 || *str2){
        if(*str1 > *str2){
            return 1;
        }else if(*str1 < *str2){
            return -1;
        }
        str1++;
        str2++;
    }
    return 0;
}

/*
int myStrcmp(char *str1, char *str2){
    int index = 0; // 3
    //      \0                        \0
    while(str1[index] != '\0' || str2[index] !='\0'){
        //      3           3
        if(str1[index] > str2[index]){
            return 1;
        }else if(str1[index] < str2[index]){
            return -1;
        }
        index++;
    }
    return 0;
}
*/

6、高级指针之和指向函数的指针

#include <stdio.h>
void test();
int main()
{
    /*
     * 指针变量的作用: 专门用于保存地址
     *
     * 指向函数的指针
     * 计算机也会给函数分配存储空间, 既然函数会分配内存空间,
     * 所以函数也有自己的地址, 所以指针变量也可以保存函数的地址
     *
     * 经过前面的学习, 我们知道数组名保存的就是数组的地址
     * 函数和数组很像, 函数名中保存的就是函数的地址
     *
     * 如何定义指针变量?
     * 1.将需要保存变量的定义拷贝过来
     * 2.在数据类型和变量名称中间添加一个*
     * 3.修改变量名称
     *
     * 如何定义保存函数的指针变量
     * 1.将函数的什么拷贝过来
     * 2.在函数返回值和函数名称总监添加一个*
     * 3.修改函数名称
     * 4.注意点: 需要将*和变量名称用括号括起来
     *
     *
     * 我们说过指向函数的指针和指向数组的指针很像
     * 如果是数组, 我们可以直接将数组名称赋值给一个指针变量
     * 如果是函数, 我们也可以直接将函数名称赋值给一个指针变量
     *
     * 如果一个指针指向了数组, 那么访问数组就有了三种方式
     * 数组名称[索引];
     * 指针变量名称[索引]
     * *(指针编码名称 + 索引)
     *
     * 如果一个指针指向了函数, 那么访问方式也有多种方式
     * 函数名称();
     * (*指针变量名称)();
     * 指针变量名称();
     */
//    printf("test = %p\n", test); // test = 0040166D
//    printf("&test = %p\n", &test); // &test = 0040166D

//    int num;
//    int *p;
//    p = &num;

//    test(); // 第一种方式
    void (*funcP)();
    funcP = &test;
//    funcP = test;
//    (*funcP)(); // 第二种方式
//    funcP(); // 第三种方式


//    int ages[3] = {1, 3, 5};
//    int *p;
//    p = ages;
//    printf("ages[1] = %i\n", ages[2]);
//    printf("p[1] = %i\n", p[2]);
//    printf("p[1] = %i\n", *(p+2));

    return 0;
}
void test(){
    printf("test\n");
}
#include <stdio.h>
void say();
void sum(int a, int b);
int minus(int a, int b);
char* test();
int main()
{
    // 需求: 定义指针指向这几个函数
    void (*p1)();
    p1 = say;
    p1();

    void (*p2)(int, int);
    p2 = sum;
    p2(10, 20);


    int (*p3)(int a, int b);
    p3 = minus;
    int res = p3(10, 20);
    printf("res = %i\n", res);

    char* (*p4)();
    p4 = test;
    char* res2 = p4();
    printf("res2 = %s\n", res2);
    return 0;
}
void say(){
    printf("Hello World\n");
}
void sum(int a, int b){
    printf("res = %i\n", a + b);
}
int minus(int a, int b){
    return a - b;
}
char* test(){
    char* name = "msh";
    return name;
}
#include <stdio.h>
int sum(int num1, int num2);
int minus(int num1, int num2);
int test(int num1, int num2, int (*funP)(int, int));
int main()
{
    // 需求: 要求一个函数既可以计算两个变量的和, 也可以计算两个变量的差
    // 指向函数的指针的一个应用场景
    int res1 = sum(10, 20);
    printf("res1 = %i\n", res1);

    int res2 = minus(10, 20);
    printf("res2 = %i\n", res2);

    /*
    int (*funP)(int, int);
    funP = &sum;
    int res3 = funP(10, 20);
    printf("res3 = %i\n", res3);

    funP = &minus;
    int res4 = funP(10, 20);
    printf("res4 = %i\n", res4);
    */

    int res3 = test(10, 20, sum);
    printf("res3 = %i\n", res3);

    int res4 = test(10, 20, minus);
    printf("res4 = %i\n", res4);
    return 0;
}
int test(int num1, int num2, int (*funP)(int, int)){
    return funP(num1, num2);
}

int sum(int num1, int num2){
    return num1 + num2;
}
int minus(int num1, int num2){
    return num1 - num2;
}
#include <stdio.h>
void say();
int sum(int num1, int num2);
int minus(int num1, int num2);
int demo(int num1, int num2, int (*funcP)(int, int));
int main()
{
    /*
     * 1.如何定义一个指向函数的指针
     * 1.1将函数的什么拷贝过来
     * 1.2在函数的返回值和函数名称中间添加一个颗*
     * 1.3修改函数的名称
     * 1.4将*和函数名称用括号括起来
     *
     * 2.函数的名称就是函数的地址
     */
    /*
    void (*funcP)();
    printf("funcP = %i\n", sizeof(funcP));
    funcP = &say;
    (*funcP)();
    */

    /*
    int (*funcP)(int, int);
//    funcP = &sum;
    funcP = sum;
//    printf("&sum = %p\n", &sum);
//    printf("sum = %p\n", sum);

//    (*funcP)();
//    sum();
    int res = funcP(10, 20); // int res = 30;
    printf("res = %i\n", res);

    funcP = &minus;
    int res2 = funcP(10, 20); // int res = -10;
    printf("res2 = %i\n", res2);
    */

    int value = demo(10, 20, &sum); // 30;
    printf("value = %i\n", value);

    int value2 = demo(20, 30, &minus); // -10;
    printf("value2 = %i\n", value2);
    return 0;
}
// 注意点: 指向函数的指针,作为函数的形参时, 指针变量的名称, 就是形参的名称
// 如果指向函数的指针作为函数的参数, 那么这个可以称之为回调函数
// 这里相当于, 给demo函数传入了一个sum函数或者minus函数
// 然后又在demo函数中调用了sum函数或者minus函数
int demo(int num1, int num2, int (*funcP)(int, int)){
    int res = (*funcP)(num1, num2); // int res = 30; int res = -10;
    return res; //return 30; return -10;
}
/*
void say(){
    printf("hello wolrd\n");
}
*/
int sum(int num1, int num2){
    return num1 + num2;
}
int minus(int num1, int num2){
    return num1 - num2;
}

/*
 * 1.要求从键盘输入一个字符串, 并且字符串中可以出现空格
 * 2.将用户输入的字符串, 单词的首字母变成大写,    单词用空格划分
 * hello world;  --> Hello World;
 * 3.将用户输入的字符串, 单词的首字母编程小写,    单词用空格划分
 * Hello World;  --> hello world;
 * 4.要求定义一个函数, 既可以处理将首字母变为大写, 也可以处理将首字母变为小写
 * 需要用到指向函数的指针
 */

相关文章

  • 12 C指针

    1、指针定义 2、指针进阶 3、指针使用 4、多级指针 4、指针和数组 5、指针和字符串 6、高级指针之和指向函数的指针

  • C语言

    C 指针、指针变量、函数指针、指针函数、指针数组、数组指针、C 数组

  • 02-C语言的指针

    02-C语言的指针 目标 C语言指针释义 指针用法 指针与数组 指针与函数的参数 二级指针 函数指针 指针在C中很...

  • C语言05- 指针

    C语言05- 指针 13:指针 指针是C语言中的精华,也是C语言程序的重点和难点。 13.1:指针定义与使用 指针...

  • 带小白学C语言指针

    C语言里指针才是C语言的开始和指针;C语言里基本所有东西都是由指针演变而成; 指针是指向地址的变量,类型就是指针...

  • 学习笔记3(指针运算,函数参数与指针,数组指针,二级指针)

    一、指针运算 二、数组与指针 三、指针和函数参数 java中: C/C++中: 四、指针数组 五、 二级指针 六、...

  • C++知识点

    C++基本方法: C++ memcpy C++基本特性: C++引用(vs指针) C++指针 C++封装: 将...

  • 第九天

    2018年12月4日周二23:19 睡眠C+ 饮食C 课程D(指针太难懂了) 英语C+ 其他:练字了楷书。 总结:...

  • 再学C语言之指针要点

    C之字符数组 C之指针引用字符串 C语言之数组指针 数组指针:首先它是一个指针,它指向数组指针数组:首先它是一个数...

  • 智能指针

    指针的危害 指针未初始化 野指针 内存泄漏 参考阅读C/C++指针使用常见的坑 智能指针分类 本质:将指针封装为类...

网友评论

      本文标题:12 C指针

      本文链接:https://www.haomeiwen.com/subject/fkunnftx.html