嵌入式C语言-指针学习笔记

1、指针简介       

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

我们可以定义一个变量,通过引用变量来直接访问数据;也可以通过指针获取数据的地址,从而间接访问数据。

(1)计算机存储机制

                计算机存储机制分为大端模式和小端模式,不过目前大多数计算机采用小端模式的存储方式。

        首先,计算机存储机制是将内存划分为一个线性区域,小端模式即将数据的低位存放在对应内存的首地址,然后依次往后存放。例如,存放int型变量数据时,数据0x12345678大小为4个字节,在内存中,该变量的低位即‘78’存放于内存地址都首地址。在内存中,各数据本身是按照小端模式存储的,但是对于数组数据,各数据之间是按顺序进行存储的。

(2)指针的定义

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

        指针变量所占的字节大小是由系统位宽所决定的。

(3)指针的操作

        当'*'号单独位于指针变量前面,前面没有变量类型,那么'*'号的含义是取内容,即取出该指针指向的内存中的数据。

        指针的也加减运算是以该指针所指向的数据类型(例如int、char、short等)的位宽为单位的。例如,某指向int型数据的指针p,在经过p++操作后,指针变量p的地址加4。

        指针的加减运算通常运用在数组中,单独的指针加减运算会使指向指向一个未被定义的地址,会造成程序错误。

2、数组与指针

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

#include<stdio.h>
#include<stdlib.h>

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

3、注意事项

        在对指针取内容之前,一定要确保指针指在了合法的位置,否则将会导致程序出现不可预测的错误;

        同级指针之间才能互相赋值,跨级赋值将会导致编译器报错或警告。

4、指针的应用

(1)传递参数

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

        直接调用参数时,经历了一个复制的过程,首先变量a申请了四个字节地址,然后形参又额外申请了四个字节地址,在子函数中,将实参复制到形参中。此方法隔离了形参与实参,子函数中对形参的修改不会影响到实参的内容。

        面对大容量数据时,使用直接传参的方法工作量较大,且c语言没有提供传递数组的方法。利用指针进行间接传参,就可以减少工作量,并且减少内存的应用。首先,在子函数中,形参定义为指针变量,该指针变量在内存中申请了8个字节的地址,在函数将实参传给形参,此时,形参指针变量的地址中存放的是数组的首地址,array[i]将以此访问数组中的各元素。但是使用指针传参,子函数可以对主函数中的变量进行修改,为了避免子函数对主函数变量的影响,可以在子函数形参的变量类型前加“const”进行修饰,关键字const用来定义常量,如果一个变量被const修饰,那么它的值就不能再被改变。

int a[] = {0x66,0x77,0x88};

        也可以定义一个全局变量,子函数和主函数都使用全局变量作为参数,那个老师说“我只能说,你要是非要这么做也行”,但是这样做不利于函数的封装。

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

        C语言的函数只能返回一个值,如果想返回多个值 应该怎么做呢?

        通过在子函数中更改主函数的值,实现多返回值函数的设计。 

#include<stdio.h>
void FindMax(int *max,int *cont,const int *arry)
{
	int i;
	*max = arry[0];
	*cont = 1;
	for(i=0;i<6;i++)
	{
		if(*max<arry[i+1])
		{
			*max = arry[i+1];
			*cont = 1;
		}
		else if(*max == arry[i+1])
		{
			(*cont)++;	
		}
	}
}
int main(void)
{	
	int a[] = {1,2,3,4,5,3};
	int Max;
	int Cont;
  
	FindMax(&Max,&Cont,a);
	printf("%d\n",Max);
	printf("%d\n",Cont);
	
	return 0; 	
}

(2)传递返回值

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

#include<stdio.h>
int Time[] = {23,45,57};//该数组申明不能放在子函数中,因为在子函数中它只是一个临时变量,子函数结束后该变量会消失 
/*int *GetTime(void) 
{
	int Time[] = {23,45,57};
	return Time;
}*/                 // 例如该用法是错误的 

int *GetTime(void)   //看作整体,返回值是int*;数组名就是地址,整个函数中始终传递的都是Time数组的地址。 
{
	return Time;
}
int main(void)
{	
	int *pt;
	
	pt = GetTime();
	
	printf("%d\n",pt[0]);
	printf("%d\n",pt[1]);
	printf("%d\n",pt[2]);
	
	return 0; 	
}

        利用C语言读写文件

#include<stdio.h>
int main(void)
{	
    char a;
	FILE *f = NULL;

	f = fopen("D:\\text.txt","r");//
	a=fgetc(f);
	fputc('A',f);
	fputs("\nHelloWorld!",f);
	fclose(f);
	printf("a=%c\n",a);
	return 0;
}

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

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

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

1)利用指针传递数组

#include<stdio.h>

unsigned char AirData[20];

void SendData(unsigned char *data,unsigned char count) 
{
	unsigned char i;
	for(i=0;i<count;i++)
	{
		AirData[i]=data[i];
	}
}

int main(void)
{	
   unsigned char DataSend[]={0x12,0x34,0x52,0x64};
   SendData(DataSend,4);
   printf("%x\n",AirData[0]);
   printf("%x\n",AirData[1]);
   printf("%x\n",AirData[2]);
   printf("%x\n",AirData[3]);
   return 0;
} 

2)利用指针发送浮点型变量

#include<stdio.h>

unsigned char AirData[20];
unsigned char DataReceive[4];
float a=12.345;

void SendData(unsigned char *data,unsigned char count) 
{
	unsigned char i;
	for(i=0;i<count;i++)
	{
		AirData[i]=data[i];
	}
}

void ReceiveData(unsigned char *data,unsigned char count) 
{
	unsigned char i;
	for(i=0;i<count;i++)
	{
		data[i]=AirData[i];
	}
	
}
int main(void)
{	
	unsigned char *p;
	p = (unsigned char *)&a;
	SendData(p,4);
    float *fp;
    ReceiveData(DataReceive,4);
    fp = (float *)DataReceive;
   printf("%f\n",*fp);
   
   return 0;
} 

完结!

第一篇,可能只有自己懂,希望可以坚持下来,再接再厉!

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值