自学内容网 自学内容网

嵌入式入门Day16

在这里插入图片描述

指针变量的使用

指针变量和字符串的关系

  1. " hello world":字符类型的数组,本质是一个地址
    520:整形类型
    ‘A’:小数类型
    3.14:实数类型
  2. 字符串的本质是一个地址,可以使用一个指针变量存储该地址
    char *p = “hello world”;
  3. 字符串常量存储在静态区的只读区域,如果对上面这个指针 p修改的话将会出现段错误

指针进阶

指针函数

  1. 指针函数本质上是一个函数,返回值为指针的函数就是指针函数
  2. 指针函数调用的结果是一个左值
  3. 指针函数返回的必须是一个生命周期比较长的空间的地址,不能返回局部空间的地址
    • 全局变量的空间
    • 静态变量的空间
    • 堆区申请的空间
    • 主调函数以地址传入的空间
  4. 指针函数实现了将被调函数中的内存传递给主调函数使用
  5. 定义格式:返回值类型 *函数名(参数列表){函数体;return 地址;}
#include <stdio.h>


//值返回函数
int fun_1(int n)
{
n += 10;
return n;
}

//地址返回函数
int *fun_2()
{
static int s = 66;
return &s;
}

int main(int argc, const char *argv[])
{
int num = 520;

//调用功能函数1
int res = fun_1(num); //值返回函数,结果为右值,只读

printf("res = %d\n", res);
//  fun_1(num) = 1314; //值返回函数不能作为左值 报错

int *ptr = fun_2();
printf("*ptr = %d\n", *ptr);

*fun_2() = 777; //指针函数的返回值是一个左值
return 0;
}

函数指针

  1. 函数指针本质上是一个指针,用于指向函数的入口地址的指针
    任何函数在被调用时系统都会为其分配运行空间,有空间就会有地址,有地址就可以用指针变量来指向他。存储函数运行空间地址的指针变量称为函数指针变量
  2. 任何一个函数的函数名都是该函数对应的入口地址,是一个地址常量
  3. 函数指针定义格式:返回值类型 (* 变量名)(参数列表);
  4. 函数指针变量的用法:和函数名用法一致
#include <stdio.h>

int sum(int m, int n)
{
return m+n;
}

int judge(int m)
{
return m%2 == 0 ? 1 : 0;
}

void sort(int *arr, int n)
{
for (int i = 1; i < n; i++)
{
for (int j; j < n-i; j++)
{
if (arr[j] > arr[j+1])
{
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
printf("排序成功\n");
}

int main(int argc, const char *argv[])
{
//打印三个函数的地址
printf("%p\t%p\t%p\t\n", sum, judge, sort);

//定义指针存储上面三个函数的入口地址
int (*sum_ptr)(int,int) = sum;
int (*judge_ptr)(int) = judge;
void (*sort_ptr)(int *,int) = sort;

//函数和函数指针都可以正常调用
printf("和为: %d\n", sum(1,4));
printf("和为: %d\n", sum_ptr(1,4));

if (judge(56))
{
printf("是一个偶数\n");
}else
{
printf("是一个奇数\n");
}

if (judge_ptr(56))
{
printf("是一个偶数\n");
}else
{
printf("是一个奇数\n");
}

return 0;
}

  1. 使用函数指针完成函数回调(回调函数)
    函数回调:当调用某个函数时,不仅要向该函数中传递数据参数,也可以向该函数中传入一个功能
#include <stdio.h>

int he(int m,int n)
{
return m+n;
}

int cha(int m, int n)
{
return m-n;
}

int ji(int m, int n)
{
return m*n;
}

//使用传入的函数指针调用别的函数
void calculate(int m, int n,int (*x)(int,int))
{
int res = x(m,n);
printf("结果为:%d\n", res);
}

int main(int argc, const char *argv[])
{
int num = 3, key = 6;

calculate(num, key, he);
calculate(num, key, cha);
calculate(num, key, ji);

return 0;
}

数组指针

  1. 数组指针的本质是一个指针,记录的是整个数组的地址
    数组指针针对的是整个数组,每偏移一个单位,内存地址就偏移了整个数组的大小
  2. 数组指针的定义格式:数据类型 (*指针名)[数组长度];
  3. 数组指针与一维数组的关系
    • 数组名是第一个元素的地址 ----> 变量的地址
    • 对一维数组名,再取地址,就得到了当前数组的地址(数组的地址)
#include<stdio.h>

int main(int argc, const char *argv[])
{
    int arr[5] = {4,7,2,8,1};    //定义了一个长度为5的数组

    int *ptr = arr;       //普通元素的地址
    
    //定义一个指针变量,存储整个数组的地址
    int (*arr_ptr)[5] = NULL;   //定义一个数组指针
    arr_ptr = &arr;           //将数组指针指向整个数组    *arr_ptr = *&arr


    printf("sizeof(arr) = %ld\n", sizeof(arr));    //20


    printf("ptr = %p,arr=%p, &arr[0]=%p, &arr = %p,arr_ptr=%p\n",\
            ptr, arr, &arr[0], &arr, arr_ptr);

    printf("ptr+1 = %p,arr+1=%p, &arr[0]+1=%p, &arr+1 = %p, arr_ptr+1=%p\n",\
            ptr+1, arr+1, &arr[0]+1, &arr+1, arr_ptr+1);

    //使用数组指针访问元素
    printf("数组元素分别是:");
    for(int i=0; i<5; i++)
    {
        //printf("%d\t", (*arr_ptr)[i]);    // *arr_ptr ==> *(arr_ptr+0) ==> arr[0]
        printf("%d\t", arr_ptr[0][i]);    // *arr_ptr ==> *(arr_ptr+0) ==> arr[0]
    }
    return 0;
}
  1. 数组指针与二维数组的关系
    • 二维数组的数组名本质上是一个数组指针
    • 当数组指针与二维数组结合后,指针的偏移才有现实的意义
#include<stdio.h>

int main(int argc, const char *argv[])
{
    int arr[2][3] = {{1,2,3}, {4,5,6}};    //定义一个二维整型数组
    //从元素的角度:定义了6个整形变量
    //从数组的角度:定义了两个一位数组
    
    //int *ptr = arr;        //?不可以进行  int *ptr=arr[0]
    
    int (*arr_ptr)[3] = arr;     //定义数组指针存储二维数组名


    printf("&arr[0][0]=%p, arr[0]=%p, arr=%p, arr_ptr=%p\n",\
            &arr[0][0], arr[0], arr, arr_ptr);

    printf("&arr[0][0]+1=%p, arr[0]+1=%p, arr+1=%p, arr_ptr+1=%p\n",\
            &arr[0][0]+1, arr[0]+1, arr+1, arr_ptr+1);

    //使用数组指针访问元素
    //arr_ptr 表示的是第一行的整体地址  
    
    //arr_ptr+i :表示任意一行的整体地址 
    
    //*(arr_ptr+i) :表示任意一行的第一个元素的地址  --> arr_ptr[i]
    
    //*(arr_ptr+i) +j :表示的是下标为i和j的元素的地址 --> arr_ptr[i]+j
    
    // *(*(arr_ptr+i)+j):表示任意一个元素   --> *(arr_ptr[i]+j)  -->arr_ptr[i][j]
    
    printf("数组元素分别是:\n");
    for(int i=0; i<2; i++)
    {
        for(int j=0; j<3; j++)
        {
            //printf("%d\t", arr_ptr[i][j]);
            printf("%d\t", *(*(arr_ptr+i)+j));
        }
        printf("\n");
    }
    
    return 0;
}

指针数组

  1. 指针数组本质上是一个数组,但是每个元素都是一个指针变量
  2. 定义格式:数据类型 *数组名 [数组长度]

函数指针数组

  1. 函数指针数组本质上是一个数组,数组中的每个元素都是一个函数指针变量,都可以存储函数入口的地址
  2. 能够实现对函数的批量调用
  3. 定义格式:返回值类型 (* 数组名[数组长度])(形参列表)

二级指针

  1. 每个指针变量都占有内存空间,有空间就有地址,就可以使用指针存储他的地址
  2. 存储一级指针变量的地址的指针变量就是二级指针变量
    一级指针变量的地址为二级指针
  3. 定义格式:数据类型 **指针名
  4. 二级指针变量的值为:一级指针变量的地址
    二级指针指向的内存空间中的值是一级指针(也就是变量的地址)—> *二级指针变量
    二级指针取值两次是变量的值 —> **二级指针变量
  5. 二级指针变量常用于函数参数为主程序中的一级指针变量进行赋值

万能指针

  1. 万能指针就是可以接收任意地址的指针变量
  2. 定义格式:void *指针名
  3. 由于没有任何类型的限制,导致该指针变量可以接收任意类型的地址
  4. 对于万能指而言不能直接进行*运算

原文地址:https://blog.csdn.net/2301_77682837/article/details/143934059

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!