江科大 C语言 指针的详解与应用

指针简介

指针(Pointer)是C语言的一个重要知识点,指针与底层硬件联系紧密,使用指针可操作数据的地址,实现数据的间接访问。

计算机存储机制

右边这个图就是我们实际的内存的一个框图,那么在我们计算机的内存里呢,我们通常把内存分配成这样一个线性的空间,就内存分配为一个线性的区域,每个区域都是以字节为单位的,比如0x78就是一个字节数据,每个字节都会对应一个地址。

比如我们定义了一个整型的int型变量a,给它赋值为0x12345678,在计算机系统里,int代表的是一个4个字节的数据,所以一个int类型的变量就跨越了4个地址,这种把小端(78)放在内存的第一位的存储模式叫小端存储模式,同样也有把大端(12)放在第一位的这种大端存储模式。short代表2给字节的数据,也是同样的小端存储模式。 而我们定义一个数组,它的每一个数据都是按顺序来存储的,char代表一个1个字节的数据,用char定义了一个数组,如图所示它的每一个数据都是按顺序来存储的,而当我们用short定义数组,数组中的一个元素占用2个字节,每个元素都是按照顺序来存储的,而元素内部的数据则分开从小端储存。

定义指针

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

指针占用的位宽等于系统的位宽,为什么呢?

首先补充,位(bit)和字节(byte)都是电脑的计量单位。字节是电脑中最基本的单位,它用于衡量电脑的存储容量,一个存储单元能存储一个字节的内容,即8个二进制位的内容。一个8位宽的设备,一次可以处理一个字节。

因为指针需要存储足够的信息来定位内存中的数据。例如,在32位的系统中,指针的位宽也是32位,它可以存储2^32个可能的地址,这足以覆盖整个32位系统的内存空间。

通过sizeof我们也可以看出指针变量和普通变量所占字节的差别。

指针的操作

*p是以p存储的地址为引导取该地址存储数据的内容

P++指针向下移动一个数据宽度,此数据宽度指的是指针指向变量a的数据宽度。

数组与指针

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

注意事项

指针的应用

 传递参数

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

#include<stdio.h>

int FindMax(int*array,int Count)//这里定义了一个局部指针变量array,申请了8个字节的内存,这是形参,储存了一个指向数组a首地址的指针,通过指针间接访问了数组a的内容
{
    int i;
    int max=array[0];
    for(i=1;i<Count;i++)
    {
        if(array[i]>max)
        {
            max=array[i];
        }

    }
    return max;
}

int main(void)
{
    int a[]={13,2,3,5,4,30};//数组传参时只能间接访问
    int Max;

    Max=FindMax(a,6);//这是实参

    return 0;
}

有时为了防止子函数篡改主函数内容,常在形参定义前加上const

这个过程内部经历了什么?

 在主函数中int a[]={13,2,3,5,4,30}先用6*4个字节储存了数组的数据,又用4个字节定义了一个Max,此时到了Max=FindMax(a,6)将数组a的首地址传入子函数,首先,子函数中定义了一个局部变量array,这个变量是int*,所以他会再申请8字节的内存,形参定义了一个指针变量,并且把a值赋给形参这个初始值,array的初始值就是a,当走到max=array[0],首先array[0]是取出array当作指针下的第一个数据,我们并不把a取出来,而是把a当作地址去找这个地址下的内容,这里的array[0]和主函数中a[0]是同一个数组,同一个地址。

数组名本身就是指针常量,他的值是该数组首元素的地址,而在子函数中定义的局部指针变量,其实就是把实参赋给形参都是指针,只是创建的array指针变量变成了指向数组a首地址的指针,仅此而已。

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

#include<stdio.h>

void FindMaxandCount(int*max,int*count,int*array,int length)
{
    int i;
    *max=array[0];
    *count=1;
    for(i=1;i<length;i++)
    {
        if(array[i]>*max)
        {
            *max=array[i];
            *count=1;
        }
        else if(array[i]==*max)
        {
            (*count)++;
        }
    }

}



int main()
{
    int a[]={13,2,3,5,4,30};
    int Max;
    int Count;
    
    FindMaxandCount(&Max,&Count,a,sizeof(a)/sizeof(a[0]));
    
    printf("Max=%d Count=%d",Max,Count);

    return 0;

}

将地址赋给指针,让指针指向此地址,在用*取内容实现间接访问

传递返回值

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

#include<stdio.h>

int main(void)
{
    char a;
    char s[10];
    FILE *f=fopen("F:\\test.txt","r");//f就是句柄

    a=fgetc(f);
    fgets(s,15,f);
    
    fclose(f);

    printf("%c",a);
    printf(s);

    return 0;
}

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

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

#include<stdio.h>
#include"LCD1602.h"

void main()
{
    unsigned char code*p;

    LCD_Init();
    LCD_ShowString(1,1,"HelloWorld");

    p=(unsigned char code*)0xFF9;
    
    LCD_ShowHexNum(2,1,*P,2);
    LCD_ShowHexNum(2,3,*(p+1),2);
    LCD_ShowHexNum(2,5,*(p+2),2);
    LCD_ShowHexNum(2,7,*(P+3),2);
    LCD_ShowHexNum(2,9,*(P+4),2);
    LCD_ShowHexNum(2,11,*(P+5),2);
    LCD_ShowHexNum(2,13,*(P+6),2);

    while(1)
    {



    }

}

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

#include<stdio.h>

/******************************************************************/

unsigned char AirData[20];

void SendData(const 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()
{
    unsigned char i;
    unsigned char DataSend[]={0x12,0x34,0x56,0x78};
    float num=12.345;

    unsigned char*p;

    p=(unsigned char *)&num

    SendData(p,4);
    /**************************************/
    printf("\nAirData=");
    for(i=0;i<20;i++)
    {    
        printf(%x,AirData[i]);
    }
/***********************************************/
    unsigned char DataReceive[4];

    float *fp;

    ReceiveData(DataReceive,4);
    
    fp=(float *)DataReceive;
    
    printf("\nnum=%f",*fp);

    //printf("\nDataReceive=");
    //for(i=0;i<4;i++)
   // {
       // printf("%x ",DataReceive[i]);
   // }

    return 0;


}

  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值