0
点赞
收藏
分享

微信扫一扫

指针补充

知识点8【指针数组】

指针数组:本质数组 只是数组的每个元素位指针变量(保存地址编号)

指针补充_指针变量

指针数组 主要用于存放多个相同类型地址编号。

指针补充_一维数组_02

知识点9【指针变量的内存布局分析】

指针补充_指针数组_03

指针补充_一维数组_04

知识点10【字符数组和字符串指针变量的关系】

//字符数组:buf是数组 用数组本身的空间存储字符串
char buf[128]="hello world";

//字符串指针变量:buf是指针变量 保存了字符串"hello world"的首元素地址 
//而"hello world"却在文字常量区
char *buf = "hello world";

指针补充_指针数组_05

char buf1[128]="hello world";
buf1[1]='E';//ok
char *buf2="hello world";
buf2[1]='E';//eror 

知识点11【字符指针数组】

指针补充_指针变量_06

知识点12【指针的指针】

指针补充_指针数组_07

知识点13【数组指针】

1、一维数组的首元素地址首地址

指针补充_数组_08

printf("%d\n", *((int *)(&arr+1)-2)); == 40

2、数组指针

数组指针:本质是指针变量 保存的是数组的首地址

指针补充_一维数组_09

指针补充_指针数组_10

3、数组指针 主要和 二维数组配合

指针补充_一维数组_11

指针补充_一维数组_12

一维数组指针int (*p)[4] 和二维数组名的int arr[3][4]操作等价

二维数组指针int (*p)[4][5]和三维数组名的int arr[3][4][5]操作等价

int arr[5];
int *p =arr;
//p是指针变量p++ 只占4B,但是arr不能++ arr的大小有元素的个数*每个元素的大小决定

int arr[3][4];
int (*p)[4];

//二维数组名 代表第0行的行地址  对行地址取* 代表当前行第0列的列地址  对列地址取* 代表元素值
arr[1]+1 第一行第1列的列地址
*arr+1 第0行第1列的列地址
**arr 第0行第0列的值
*(&arr[1]+1) == *(arr+2) == 第2行第0列的地址
*(arr+1)+1 第1行第1列的列地址
*arr[1]+1  第1行第0列的值+1

知识点14【指针作为函数的形参】

1、如果函数内部修改外部变量的 必须传递外部变量的地址

错误演示:

//单向传递:之传值 函数内部无法借助形参 修改外部变量的值
void set_data(int a)
{
    a = 1000;
}
void test01()
{
    int data = 10;
    set_data(data);
    printf("data=%d\n",data);//10
}

函数内部需要操作外部普通变量的值 需要将外部普通变量的地址 传递给函数

指针补充_数组_13

错误演示:

指针补充_指针数组_14

如果函数内部需要 给外部指针变量 修改指向 需要将外部指针变量的地址传递给函数

指针补充_一维数组_15

2、函数内部 想操作 外部一维数组 需要将一维数组名作为实参传递给函数。

所以:函数的形参 就是一维数组的元素指针变量

//void my_print_int_array(int arr[5], int n)
void my_print_int_array(int *arr, int n)
{
    int i=0;
    for ( i = 0; i < n; i++)
    {
        //printf("%d ", *(arr+i));
        printf("%d ", arr[i]);
    }
    printf("\n");
}
void my_input_int_array(int *arr, int n)
{
    printf("请输入%d个int数值:",n);
    int i=0;
    for ( i = 0; i < n; i++)
    {
        scanf("%d", arr+i);
        //scanf("%d", &arr[i]); 
    }
    printf("\n");
}
int get_int_array_avg(int *arr,int n)
{
    int sum=0,i=0;
    for ( i = 0; i < n; i++)
    {
        sum+=arr[i];//如果是元素的值arr[i]  如果是元素地址arr+i
    }

    return sum/n;
}
void get_max_min_data(int *arr,int n,int *p_max,int *p_min)
{
    int i=0;
    //*p_max = arr[0];
    int max = arr[0];
    int min = arr[0];
    for (i = 1; i < n; i++)
    {
        //*p_max = ((*p_max<arr[i])?arr[i]:*p_max);
        max = ((max<arr[i])?arr[i]:max);
        min = ((min>arr[i])?arr[i]:min);
    }

    //*p_max ==外部的max  *p_min ==外部的min
    *p_max = max;
    *p_min = min;
    return;
}
void test03()
{
    int arr[5]={0};
    int n=sizeof(arr)/sizeof(arr[0]);

    my_input_int_array(arr, n);

    my_print_int_array(arr, n);

    //需求:求数组中的平均值
    int avg = 0;
    avg = get_int_array_avg(arr,n);
    printf("平均值:%d\n", avg);

    //需求:求数组中的最大值和最小值
    int max=0,min=0;
    get_max_min_data(arr,n,&max,&min);
    printf("max=%d,min=%d\n",max,min);

    return;
}

#include <string.h>
void input_char_array(char *buf, unsigned long len)
{
    printf("请输入一个字符串:");
    fgets(buf,len,stdin);
    buf[strlen(buf)-1]='\0';
    return;
}
void my_strcpy(char *dst, char *src)
{
    while(  (*dst=*src) && dst++ && src++ );
    return;
}
void test04()
{
    char buf[128]="";

    //定义函数完成buf输入
    input_char_array(buf, sizeof(buf));

    char dst[128]="";
    //定以函数完成strcpy
    my_strcpy(dst, buf);
    printf("dst=%s\n", dst);
}

一维数组作为函数的形参 会被优化成 元素指针变量

int arr[5]------->int *arr
char arr[128]------>char *arr

3、如果函数内部 需要操作 外部二维数组元素 需要将二维数组名作为实参传递给函数。

所以:函数的形参 就是 数组指针

    实参----------->形参
int arr[3][4]------>int (*p)[4]
int arr[3][4][5]------>int (*p)[4][5]
char arr[3][128]---->char (*p)[128]

// void print_two_int_array(int arr[3][4],int row, int col)
void print_two_int_array(int (*arr)[4], int row, int col)
{
    int i = 0;
    for (i = 0; i < row; i++)
    {
        int j = 0;
        for (j = 0; j < col; j++)
        {
            // printf("%d ", *(*(arr+i)+j));
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    return;
}
void test05()
{
    int arr[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    int row = sizeof(arr) / sizeof(arr[0]);
    int col = sizeof(arr[0]) / sizeof(arr[0][0]);

    print_two_int_array(arr, row, col);
}

知识点15【函数的返回值为指针类型】

函数如果想 将函数内部空间 给外部使用 一般通过函数返回值 将内部空间起始地址 返回给部。

所以函数的返回值类型必须是 指针类型

1、注意:函数不要返回栈区的空间地址(函数结束 函数内部栈区空间将释放)

int *get_addr(void)
{
    int data = 10;
    return &data;
}
void test06()
{
    int *p = NULL;
    //函数结束 data的空间释放
    p = get_addr();
    //*p操作以释放的空间 多错误
    printf("%d\n", *p);//段错误
}

2、函数内部要返回的空间 尽量全局区(static)、堆区

函数结束 全局区(static)、堆区空间 不会自动释放。

指针补充_指针数组_16

知识点16【函数指针】

函数指针:函数指针变量 保存函数的入口地址。

1、函数入口地址

在c语言中 函数名 代表函数的入口地址

指针补充_数组_17

2、函数指针变量

本质:是变量 保存的是函数的入口地址。

int my_add(int a,int b)
{
    return a+b;
}
int my_sub(int a,int b)
{
    return a-b;
}
void test01()
{
    int (*p)(int,int) = NULL;
    printf("%lu\n",sizeof(p));//8B

    p = my_add;

    //函数调用的本质:入口地址+();
    printf("%d\n", p(10,20));//30
    printf("%d\n", my_add(10,20));//30

    p = my_sub;
    printf("%d\n", p(10,20));//-10
    printf("%d\n", my_sub(10,20));//-10
}

3、函数指针变量的注意事项

不要对函数指针变量取* 无意义 编译器会优化调用。

不要对函数指针变量 ++ -- 无意义

函数指针变量 比较大小 无意义 (==除外)

4、函数指针的扩展

1、给函数指针类型取别名

int my_add(int a, int b)
{
    return a + b;
}
int my_sub(int a, int b)
{
    return a - b;
}
void test02()
{
    //typedef 为已有的类型取别名
    typedef int (*F_TYPE)(int, int);
    F_TYPE p = my_add;
    printf("%d\n", p(10,20));
}

2、函数指针 主要 作为函数的形参。

目的:让函数通用

int my_add(int a, int b)
{
    return a + b;
}
int my_sub(int a, int b)
{
    return a - b;
}
int my_mul(int a, int b)
{
    return a * b;
}
int my_div(int a, int b)
{
    return a / b;
}

// 需求:设计一个算法 完成加减乘除
int my_calc(int a, int b, int (*func)(int, int))
{
    return func(a, b);
}
void test02()
{
    printf("%d\n", my_calc(10, 20, my_add));
    printf("%d\n", my_calc(10, 20, my_sub));
    printf("%d\n", my_calc(10, 20, my_mul));
    printf("%d\n", my_calc(10, 20, my_div));
}

指针补充_一维数组_18

案例:键盘输入add 10 20 sub 10 20 mul 10 20

int my_add(int a, int b)
{
    return a + b;
}
int my_sub(int a, int b)
{
    return a - b;
}
int my_mul(int a, int b)
{
    return a * b;
}
int my_div(int a, int b)
{
    return a / b;
}
#include <string.h>
void test02()
{
    //函数指针数组 本质是数组 每个元素是函数的入口地址
    int (*fun_arr[])(int,int) = {my_add,my_sub,my_mul,my_div};
    int n = sizeof(fun_arr)/sizeof(fun_arr[0]);
    //字符指针数组
    char *cmd_buf[]={"add","sub","mul","div"};
    
    printf("请输入操作命令(add 10 20):");
    char cmd[32]="";
    int data1=0,data2=0;
    scanf("%s %d %d", cmd,&data1,&data2);

    //核心代码
    int i=0;
    for ( i = 0; i < n; i++)
    {
        if(strcmp(cmd,cmd_buf[i]) == 0)
        {
            printf("%d\n", fun_arr[i](data1,data2));
        }
    }
    
    return;
}

举报

相关推荐

0 条评论