嵌入式C语言(7)——江科大指针的详解与应用_江科大嵌入式-程序员宅基地

技术标签: 算法  c语言  开发语言  

一、指针的详解

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. 打印出转换结果。

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_52153072/article/details/132739632

智能推荐

LINUX学习-用C语言实现FTP项目_linux 下c语言开发ftp下载工具-程序员宅基地

文章浏览阅读3.2k次,点赞3次,收藏23次。FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。FTP协议包括两个组成部分,其一为FTP服务器,其二为FTP客户端。其中FTP服务器用来存储文件,用户可以使用FTP客户端通过FTP协议访问位于FTP服务器上的资源。在开发网站的时候,通常利用FTP协议把网页或程序传到Web服务器上。此外,由于FTP传输效率非常高,在网络上传输大的文件时,..._linux 下c语言开发ftp下载工具

【小白必胜-xpath】lxml.etree.HTML(),lxml.etree.fromstring()和lxml.etree.tostring()三者的区别与联系_html.fromstring()含义-程序员宅基地

文章浏览阅读3.5k次,点赞5次,收藏30次。对于使用xpath()之前的文档格式化问题,可能不同的人,会遇到不一样的情况,但是基本上只要搞懂了lxml.etree.HTML(),lxml.etree.fromstring()和lxml.etree.tostring()这三者之间的区别和联系,那么文档格式化这一步一定不会有问题……_html.fromstring()含义

Android过渡动画基础使用_gradentdrawable过渡-程序员宅基地

文章浏览阅读2k次。前言Android从API19引入了Transition过渡动画框架,它通过场景Scene概念来表述动画的关键帧,只要提供了开始和结束场景的内容就会自动做动画。过渡动画其实是对属性动画的一种封装,它能够一次对多个对象做动画而不需要特别复杂的配置。除此之外Activity之间的切换效果也可以使用过渡动画来实现。基础使用首先需要定义Scene也就是场景对象,场景其实就是某个事件点所有的..._gradentdrawable过渡

h2ouve工具使用_GitHub - sha310139/Edit_BIOS_Setting_Interface: H2OUVE是使用command修改BIOS設定的工具,此介面結合H2OUVE,對...-程序员宅基地

文章浏览阅读4.7k次。Edit_BIOS_Setting_Interface簡介H2OUVE是個可透過command的方式修改BIOS設定的工具,我們利用Python3撰寫一個簡易的介面,透過H2OUVE去修改BIOS的設定,省去使用者一一下指令並修改設定檔的麻煩。當多台server需套用同一個BIOS設定時,只要先針對一台電腦修改所需的BIOS設定,匯出設定檔後,即可透過deploy kit執行這個程式,讓多台ser..._h2ouve

超时尚的UI电子商务PSD分层模板,临摹学习必备-程序员宅基地

文章浏览阅读124次。用户体验或更准确地说,电子商务用户体验(UX)是所有UI的重要方面,在处理电子商务应用程序时是必需的。当前,电子商务业务变得越来越有竞争力,各种各样的选择使客户忠诚度成为无可挑剔的现象。UX主要是指用户在操作电子商务网站时的体验。UX封装了用户在经营电子商务商店时所经历的一系列印象,包括可访问性,便利性,满意度等。拥有“好”用户体验是指用户可以高效,愉快地满足其需求的情况。此外,用户体验优化与转化化不同。尽管UX优化的重点是满意度,可用性和将其推荐给朋友的热情等指标,但其他形式的优化却着眼于提高

Ubuntu18.04安装Cartographer_error: cannot launch node of type [cartographer_ro-程序员宅基地

文章浏览阅读3.4k次,点赞5次,收藏44次。你好你好#include <iostream>using namespace std;int main(int argc, char* argv[]){ return 0;}_error: cannot launch node of type [cartographer_ros/cartographer_node]: cart

随便推点

C++ map的常用用法(超详细)(*^ー^)人(^ー^*)_c++ map用法-程序员宅基地

文章浏览阅读3.8w次,点赞146次,收藏735次。map常用操作详细讲解_c++ map用法

EmEditor 主题 Minimal_emeditor主题-程序员宅基地

文章浏览阅读3.5k次。本风格源自MinimalZen风格修改,存为Minimal.eetheme,在EmEditor导入后选中即可。工具 => 所有配置属性 => 显示 => 主题 => 导入 => 是否移除旧主题,选“否” => 下来选择 Minimal 主题 => 确定[Minimal]MaxFind=3Normal=#a9b7c6,#2b2b2b,normal..._emeditor主题

C++学习笔记——C++中四个点代表什么意思?_c++四个点什么意思-程序员宅基地

文章浏览阅读8k次,点赞5次,收藏6次。问:C++中四个点代表什么意思? 答: 表示类的成员。(你说的是两个冒号“:”吧) 如类CA中有成员int a; 则:CA::a表示CA类中的成员a; 举个例子: class CA { int a; int b(); }; 那么:函数int b();的定义就必须是这样的: int CA::b() { //… }..._c++四个点什么意思

Cython的简单使用-程序员宅基地

文章浏览阅读83次。from:http://www.cnblogs.com/freeweb/p/6548208.html补充:在我mac上的加速效果:最初:runing1 time: 0.233466 sruning2 time: 0.930724 s使用Cython编译:runing1 time: 0.178522 sruning2 time: 0.646462 s使用cdef等静态变量:runi..._cython查询数据库节点属性

ES6新特总结_new easy let 选择那个不同的-程序员宅基地

文章浏览阅读250次。ES6新特性Babel转码器ECMAScript 6 简介学习网址:http://es6.ruanyifeng.com/ECMAScript是javascript标准ES6就是ECMAScript的第6个版本ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。ECMAScript 和 JavaScript 的关系ECM_new easy let 选择那个不同的

idea 如何配置软回车_idea 软换行什么意思-程序员宅基地

文章浏览阅读598次。软回车: 只是视觉上的换行, 其实文本内容并没实际换行, 这是为了我们可以直接看到整行内容, 而无需再使用鼠标水平滚动窗口idea 中可以配置编辑器软换行editor > general > 勾选 soft wrap these files: * (其中 * 表示软换行对所有文件生效)配置控制台软换行editor > console > 勾选 use soft wraps in console编辑器和控制台软换行效果如图..._idea 软换行什么意思

推荐文章

热门文章

相关标签