重新认识指针(一)

区别于上课或者做题学的指针,本文从实际应用的角度理解指针

一、指针

指针就是指针变量,指针变量里存的是地址,指针可以说就是地址,指针是指向该地址里的数据,比如int n=3,int *p=&n表示p是指向n的指针。

定义指针是 `int *p`等价于 `int* p`,int*是一个整体表示定义一个指针p,指向一个int类型的数据。
一定要区分`int p` 与`*p`,前者是定义`int*`类似于一个用于定义指针变量的关键字后者是解引用等于n;
此时int类型的数据占用4个字节,对于64位电脑,指针占用8个字节地址(不论指向什么类型数据都占8个字节地址),
p++等于地址加4,因为一个int类型占用4个字节(如果是char类型就是加1。任意类型的数组,p++就是指向下一个
值的地址,p时首地址。如果p是一个数的地址,p++没有意义,因为没有定义)。

二、指针和数组的关系

数组名就是指针,完全等价。

访问数组或者其他数据类型不能越界,即不能访问没有定义或者分配的地址。

至于定义一个int型数组a,a++地址会跨越四个字节,解引用会得到a[1]的值,但是中间的三个地址处于未定义状态,可能是之前存储在那里的任意值,也可能是垃圾值。

int *p=0x55;
int num;
num = *p;
//这是非法的,运行出错,因为0x55这个是哪个的地址,不知道。
//定义一个数组的等价形式:
int *a;
a=malloc(3*4);
*a=1;
*(a+1)=2;
*(a+2)=3;

//等价于
int a[]={1,2,3};

三、指针的作用

1.调用子函数,直接传递指针,可以节省内存,不然就是复制一份,再把复制的传给子函数。为了防止在子函数里更改传过来的地址里的值,可以用const。const具有只读功能。

//子函数:
int func(const int *array)//这里注意int *x是定义一个指针变量,接a
{ int b;
	b=array[1];//等价于b=*(arry+1);
  return b;
}

//主函数:
void main()
{
  int a=[1,2,3,4],c;
	c=func(a);
  printf("a[1]=d%",c])

}

//输出 a=3,b=2

2.实现多返回值,传递指针,在子函数解引用,不用int型的函数返回,直接在子函数对传过来的地址里的值进行修改,主函数同步修改。

//子函数:
void func(int *x,int *y)//这里注意int *x是定义一个指针变量,接&a
{
  (*x)++;
  (*y)--;
}

//主函数:
void main()
{
  int a=2,b=3;
  func(&a,&b);
  printf("a=%d,b=%d",a,b)
}

//输出 a=3,b=2

下面这个是strcpy函数的例子,传入的是两个参数,一个是char *,传入的是可以更改的str1[20]的数组首地址,一个是const char *,传入的是可以更改的str2[]的首地址。

strcpy():
char * _cdecl strcpy(char * __restrict__ _Dest, const char * __restrict__ _Source)

int main(void)
{
  char str1[20];
  char str2[]="Helloworld";
  strcpy(str1,str2);
}

3.传递函数句柄

//子函数:
int Time[]={1,2,3};
int *GetTime(void)   //这个函数的意思是返回int*类型的指针
{
  return Time;
}

//主函数:
int main(void)
{
  int *pt;
  pt=GetTime(); //这个GetTime就是函数句柄,代表int*类型的指针,也就是Time数组首地址。
  printf("pt[0]=%d",pt[0]);
  return 0;
}
//文件函数例子
fopen();
FILE *_cdes1 fopen(const char * __restrict__ _Filename, const char * __restrict__ _Mode)
fopen返回的是FILE结构体型的指针。

int main(void)
{
  char a;
  char s[10];
  FILE *f=fopen("F:\\test.txt","r"); //用FILE *接
  a=fgetc(f);   //此时的f就是函数(文件)句柄
  fclose(f);
}

4.将复杂类型数据转换成字节传输

对于串口传输时一个字节一个字节传输,而float类型数据并不方便字节传输

如定义float a=12.345,float类型数据占用四个字节,但是时经过编码后再存储的,如科学计数法等。

方法就是把float数据看作为数组。发送四个字节,如此时的a占用四个字节分别是Airdata[]=1f,85,45,41,再用float*强制类型转换把数组解码得到最后的float。

//发送:
float num=12.345;
unsigned char *p;
p=(unsigned char *)#//,num的地址是float型指针,强制类型转换成unsigned char *类型的指针
SendData(p,4);//**即把num看作是一个数组**,传入首地址,SendData函数解引用指针p,遍历存入定义的Airdata[]

/*************************/
//接收:
float *fp;
ReceiveData(DataReceive,4);//ReceiveData函数传入DataReceive首地址,把Airdata[]存入DataReceive[]
fp=(float *)DataReceive;//用float*强制类型转换把数组解码得到最后的float
printf("num=%f",*fp);

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

//某程序存储器flash的最后7个字节单元是全球唯一ID号
//8k的程序空间即8*1024个bit,8*(2^10)=2^13个bit,(0000 0000 0000 0000到0001 1111 1111 1111)
//**7个字节单元在7个地址,一个地址放一个字节,从0x1FF9到0x1FFF有7个地址。**
unsigned char code *p;//code表示是读程序存储器flash里的,否则默认为RAM。
p=(unsigned char code *)0x1FF9;*p,*(p+1),*(p+2),*(p+3),*(p+4),*(p+5),*(p+6)组成的数就是ID号

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值