嵌入式C语言(7)——江科大指针的详解与应用

2023-12-18 11:39:25

一、指针的详解

1、指针简介

指针(Pointer)是C语言的一个重要知识点,其使用灵活、功能强大,是C语言的灵魂

指针与底层硬件联系紧密,使用指针可操作数据的地址,实现数据的间接访问

(1)计算机存储机制

字节 byte? ? 位?bit

位等价于bit,同一单位,最小的单位

1位=1bit;1字节=8位(两个16进制数)

1字=16位;1字=2字节

在32位系统中,int?类型通常为4个字节,占32比特。

在64位系统上,int类型通常为8个字节,占64比特。

int a = 0x12345678;

0x代表进制,4个字节要存储到4个内存地址中?

(2)指针的定义

指针即指针变量,用于存放其他数据单元(变量/数组/结构体/函数等)的首地址。若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元,若指针存放的值是0,则这个指针为空指针。

对于首地址的理解:

int a = 0x12345678;

int *p = &a;

p中存储的是变量的首地址0x4000,一次读取4个字节。

定义一个指针变量:

(3)指针的操作

若已定义: ??

int a;?? ??? ?//定义一个int型的数据 ?? ?

int *p;?? ??? ?//定义一个指向int型数据的指针

则对指针p有如下操作方式:

#include <stdio.h>

int main(void)
{
    char a = 0x66;
    char *p;\\定义一个指向字符的指针变量,大小与系统的架构相关,但与其指向的数据类型无关。
    p = &a;\\&a取出变量a的内存地址,这个地址赋值给指针变量p,现在p "指向" 变量a的内存
    printf("%x\n",a);
    printf("%x\n",p);
    printf("%x\n",*p);
    return 0;
}

? ? ?(4)数组与指针

数组是一些相同数据类型的变量组成的集合,其数组名即为指向该数据类型的指针。数组的定义等效于申请内存、定义指针和初始化。

例如: ?? ?char c[ ] = {0x33, 0x34, 0x35};

等效于:?? ?申请内存 ?? ??? ?

? ? ? ? ? ? ? ? ? 定义 char *c = 0x4000; ?? ???

? ? ? ? ? ? ? ? ? 初始化数组数据

利用下标引用数组数据也等效于指针取内容

c[0];?? ?等效于:?? ?*c; ?? ???

?c[1];?? ?等效于:?? ?*(c+1); ?? ???

?c[2];?? ?等效于:?? ?*(c+2);

#include <stdio.h>

int main(void)
{
    char a[] = {0x33,0x34,0x35};
    char *p;
    p = a;
    printf("a[0]=%x\n",a[0]);\
    printf("a[1]=%x\n",a[1]);
    printf("a[2]=%x\n",a[2]);
    printf("*p=%x\n",*p);
    printf("*(p+1)=%x\n",*(p+1));
    printf("*(p+2)=%x\n",*(p+2));
    printf("%d\n",sizeof(a));
    printf("%d\n",sizeof(p));
    return 0;
}

运行结果:

(5)注意事项

在对指针取内容之前,一定要确保指针指在了合法的位置,否则将会导致程序出现不可预知的错误 同级指针之间才能相互赋值,跨级赋值将会导致编译器报错或警告

二、指针的应用

传递参数

使用指针传递大容量的参数,主函数和子函数使用的是同一套数据,避免了参数传递过程中的数据复制,提高了运行效率,减少了内存占用

#include <stdio.h>

int FindMax(int *array,int count)
{
    int i;
    int max = array[0];
    for(i=0;i<count;i++)
    {
        if(array[i]>max)
        {
            max = array[i];
        }
    }
    return max;
}
int main(void)
{
    int a[] = {1,2,3,5,4,3};
    int Max;
    Max = FindMax(a,6);
    printf("the max is %d\n",Max);
    
    return 0;
}

是一个利用指针和函数找出数组最大值的示例程序。分析如下:

1. #include <stdio.h> 导入标准输入输出头文件。

2. 定义函数FindMax,参数是int指针array和元素个数count。

3. 在函数内部,通过array指针可以访问数组内容。

4. 使用for循环和if条件判断,找出数组中的最大值。

5. main函数中定义了数组a并初始化。6

. 调用FindMax函数,传入数组a和元素个数。

7. FindMax通过指针访问数组,比较找最大值。

8. 将返回的最大值存储在Max变量中。

9. 最后打印出Max。

整个程序 demonstration了如何利用指针和函数参数实现对数组的操作。主要注意的是FindMax如何通过指针array访问数组内容,这避免了数组拷贝,提高了效率。

使用指针传递输出参数,利用主函数和子函数使用同一套数据的特性,实现数据的返回,可实现多返回值函数的设计

#include <stdio.h>

void FindMaxAndcount(int *max,int *count,const int *array,int length)
{
    
    int i;
    *max = array[0];
    *count = 1;
    for(i = 1;i < length;i++)
    {
        if(*max < array[i])
        {
            *max = array[i];
            *count = 1;
        }
        else if(*max == array[i])
        {
            *count = *count + 1;
        }
    } 
   
}
int main(void)
{
    int a[] = {13,2,3,5,4,3};
    int Max;
    int count;
    FindMaxAndcount(&Max,&count,a,sizeof(a)/sizeof(a[0]));
    printf("the Max is %d\n",Max);
    printf("the count is %d\n",count);
    
    return 0;
}

这个程序使用了指针和函数来找出数组中的最大值及其出现的次数。主要步骤:

1. 定义函数FindMaxAndCount,参数有:??- 最大值的指针max??- 次数的指针count??- 数组的指针array??- 数组长度length

2. 在函数中,通过array指针访问数组元素。

3. 使用循环和比较找出最大值,存入*max。

4. 同时统计最大值出现的次数,存入*count。

5. main函数定义数组a,调用函数并传入参数:??- &Max - 最大值的指针??- &count - 次数的指针??- a - 数组??- 数组长度

6. 函数执行后,Max和count通过指针返回结果。

7. 打印出最大值和次数。

这里的关键是利用指针参数进行传参和返回结果,避免了数组的复制。

传递返回值

将模块内的公有部分返回,让主函数持有模块的“句柄”,便于程序对指定对象的操作

#include <stdio.h>
/***********************/
 int Time[]={23,59,55};
 int *GetTime(void)
 {
     return Time;
 }
 /***********************/
 
int main(void)
{
    int *p;
    p = GetTime();
    printf("the time is %d:%d:%d\n",*p,*(p+1),*(p+2));
    return 0;
}

这个程序演示了如何通过函数返回指针来获取数据。主要步骤:

1. 定义一个全局数组Time[],用来存储时间。

2. 定义函数GetTime(),该函数返回Time数组的指针。

3. 在main函数中,调用GetTime(),将返回的指针存入p。

4. 通过指针p可以直接访问Time数组的元素。

5. 使用p、p+1、p+2来依次访问Time的每个元素。

6. 打印出获取的时间。

这个示例展示了通过返回指针的方式可以直接获取到需要的数据,避免了复制数组的开销。GetTime()将数组的地址作为指针返回,main函数使用该指针直接访问数组元素。这种通过指针和函数实现数据共享的方式非常高效,值得学习。

直接访问物理地址下的数据

访问硬件指定内存下的数据,如设备ID号等

将复杂格式的数据转换为字节,方便通信与存储

?

#include <stdio.h>
/***********************/
unsigned char AirDate[20];
 void SendDate(const unsigned char *date,unsigned char count)
 {
    unsigned char i;
    for(i=0;i<count;i++)
    {
        AirDate[i] = date[i];
    }
     
 }  
 /***********************/
 int main(void)
 {
    unsigned char i;
    unsigned char DateSend[]={0x01,0x02,0x03,0x04,0x05};
    SendDate(DateSend,5);
 
 /***********************/
 printf("\nAirDate=");
    for(i=0;i<5;i++)
    {
        printf("%x",AirDate[i]);
    }
 /***********************/ 
   
 void ReceiveDate(unsigned char *date,unsigned char count)
    {
        unsigned char i;
        for(i=0;i<count;i++)
        {
            date[i] = AirDate[i];
        }
    }
    unsigned char DateReceive[20];
    ReceiveDate(DateReceive,5);
    printf("\nDateReceive=");
    for(i=0;i<5;i++)
    {
        printf("%x",DateReceive[i]);
    }
    printf("\n");
    return 0;
 }

这个程序演示了通过指针在函数之间传递数组数据的方法。主要步骤:

1. 定义全局数组AirDate来模拟空中数据。

2. 定义函数SendDate,通过指针参数date发送数据。

3. main函数中初始化数据数组DateSend,调用SendDate发送。

4. SendDate通过指针拷贝DateSend到AirDate。

5. 定义函数ReceiveData通过指针参数date来接收数据。

6. main函数中定义数组DateReceive,调用ReceiveData接收数据。

7. ReceiveData通过指针从AirDate拷贝到DateReceive。

8. 打印结果。

这个示例展示了通过指针参数在函数间安全传递数组数据的过程,避免了数组复制。同时也演示了指针的方向性,SendDate和ReceiveData实现了双向数据传输。

#include <stdio.h>
/***********************/
unsigned char AirDate[20];
 void SendDate(const unsigned char *date,unsigned char count)
 {
    unsigned char i;
    for(i=0;i<count;i++)
    {
        AirDate[i] = date[i];
    }
     
 }  
 /***********************/
 int main(void)
 {
    unsigned char i;
    float num=12.345;
    unsigned char *p;
    p = (unsigned char *)&num;
    SendDate(p,4);
 
 /***********************/
 printf("\nAirDate=");
    for(i=0;i<20;i++)
    {
        printf("%x",AirDate[i]);
    }
 /***********************/ 
 unsigned char DateReceive[20];  
 void ReceiveDate(unsigned char *date,unsigned char count)
    {
        unsigned char i;
        for(i=0;i<count;i++)
        {
            date[i] = AirDate[i];
        }
    }
 /***********************/ 
    float *fp;
    ReceiveDate(DateReceive,4);
    fp = (float *)DateReceive;
    printf("\nnum=%f",*fp);
    
    return 0;
 }

这个程序展示了如何通过指针和类型转换在函数间传递浮点数数据。主要步骤:

1. 定义float变量num,存储要传输的数据。

2. 将num的地址强制类型转换为unsigned char指针p。

3. 调用SendDate函数,传入p和字节数4进行传输。

4. SendDate通过p指针拷贝4个字节到AirDate。

5. 在接收端,定义数组DateReceive来接收数据。

6. 调用ReceiveDate并传入DateReceive指针接收数据。

7. 将DateReceive强制转换为float指针fp。

8. 通过解引用fp指针,可以获取转换后的float数据。

9. 打印出转换结果。

通过指针和类型转换,实现了无需复制的浮点数传输。这避免了浮点数转换过程中的精度损失。同时也展示了指针和类型转换在数据传输中的强大用途。

文章来源:https://blog.csdn.net/qq_52153072/article/details/132739632
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。