指针(Pointer)是C语言的一个重要知识点,其使用灵活、功能强大,是C语言的灵魂
指针与底层硬件联系紧密,使用指针可操作数据的地址,实现数据的间接访问
字节 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个内存地址中?
指针即指针变量,用于存放其他数据单元(变量/数组/结构体/函数等)的首地址。若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元,若指针存放的值是0,则这个指针为空指针。
对于首地址的理解:
int a = 0x12345678;
int *p = &a;
p中存储的是变量的首地址0x4000,一次读取4个字节。
定义一个指针变量:
若已定义: ??
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;
}
数组是一些相同数据类型的变量组成的集合,其数组名即为指向该数据类型的指针。数组的定义等效于申请内存、定义指针和初始化。
例如: ?? ?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;
}
运行结果:
在对指针取内容之前,一定要确保指针指在了合法的位置,否则将会导致程序出现不可预知的错误 同级指针之间才能相互赋值,跨级赋值将会导致编译器报错或警告
使用指针传递大容量的参数,主函数和子函数使用的是同一套数据,避免了参数传递过程中的数据复制,提高了运行效率,减少了内存占用
#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 *)#
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. 打印出转换结果。
通过指针和类型转换,实现了无需复制的浮点数传输。这避免了浮点数转换过程中的精度损失。同时也展示了指针和类型转换在数据传输中的强大用途。