江科大笔记-C语言指针篇-指针学习、在嵌入式中的常见应用

指针介绍:

  • 指针也是个变量,或者说也是个数据类型。
  • 指针用于存放其他数据单元(变量/数组/结构体/函数等)的首地址。比如int型变量a的地址装在指针变量p上,但p自己有自己的地址
  • 若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元,若指针存放的值是0,则这个指针为空指针
  • 指向:指针变量装哪个的地址,就指向哪一个空间

定义指针变量:

  • *号:在定义指针变量时,仅仅代表一个标识符,比如其实char *是一体的,只是中间有个空格,所以看起来没有层次感,当然把*写前面也行,比如char* p;
  • 但是值得注意的是当为char* p,p1时,或者char *p,p1时,p1其实为char型,而不是个指针变量。
  • 不同系统环境,指针变量的字节x 取不同字节
    • 16位系统:x=2字节
    • 32位系统:x=4字节
    • 64位系统:x=8字节

数据类型

指向该数据类型的指针

(unsigned) char

1字节

(unsigned) char *

x字节

(unsigned) short

2字节

(unsigned) short *

x字节

(unsigned) int

4字节

(unsigned) int *

x字节

(unsigned) long

4字节

(unsigned) long *

x字节

float

4字节

float *

x字节

double

8字节

double *

x字节

指针的使用:

操作方式

举例

解释

取地址

p=&a;

将数据a的首地址赋值给p

取内容

*p;

取出指针指向的数据单元

p++;

使指针向下移动1个数据宽度

p=p+5;

使指针向下移动5个数据宽度

p--;

使指针向上移动1个数据宽度

p=p-5;

使指针向上移动5个数据宽度

  • *号:内存操作符(解引号运算符)
    • *p 表示,这个指针指向一个变量,也就是p=a,对*p进行的操作等于对a操作
    • 在定义代码 int *p 里,仅表示定义了一个指针变量名为p的标识符
    • 在其他代码里,表示取内容,即取出指针指向的数据单元,比如指针p指向a的话,即a=2,p=&a,那么*p= *&a,*和&相互抵消,所以*p=a,*p=2
#include<stdio.h>
int main(void)
   // 指针是地址型数据类型,仅此而已
{  //指针就是装指向空间地址的变量,比如a的地址装在指针变量p上,但p自己有自己的地址
   //指向:指针变量装哪个的地址,就指向哪一个空间

    int a = 12;
    int b = 15;
    int *p = &a;            //指针的定义格式:int *p;
                        //指针初始化:int *p=&a,右边记得加&符号
                        //指针类型要跟指向空间的数据类型一样!
    printf("%p,%p,%p\n", &p, p, &a);
    //&p表示变量p的地址; p表示变量p空间里装的内容,也就是a的地址,p=&a,; &a表示变量a的地址
                                                &与*互为逆运算, *p=*(&a)=a
    p = &b;                //指针赋值: 指针变量=&变量,这时不要加*号了

    printf("%p,%p,%p", &p, p, &b);

    return 0;
}
  • p++:使指针向下移动1个数据宽度
    • 数据宽度为多少?
      • 答:以指向空间的变量类型字节大小为准,比如指向一个int型,那么一个数据宽度就是4字节
//验证p++的功能

#include<stdio.h>
int main()  
{
    int a = 12;
    int* p;
    p = &a;
    printf("%d\n", a);
    printf("%d\n",p);
    printf("%d\n", *p);

    p++;

    printf("%d\n", p);

    return 0;
}

数组与指针:

  • 数组和指针其实是一个东西,只是表达形态不同
  • 数组是一些相同数据类型的变量组成的集合,其数组名即为指向该数据类型的指针。
  • 数组的定义等效于申请内存,定义指针,初始化这三个过程:

  • 利用下标引用数组数据也等效于指针取内容

 //验证数组和指针:利用下标引用数组数据也等效于指针取内容

#include<stdio.h>
int main() 
{
    int a[]={1,2,3};
    int* p;
    p = &a;
    printf("a[0]=%d\n", a[0]);
    printf("a[1]=%d\n", a[1]);
    printf("a[2]=%d\n", a[2]);

    printf("*a=%d\n", *a);
    printf("*(a+1)=%d\n", *(a+1));
    printf("*(a+2)=%d\n", *(a + 2));

    return 0;
}

注意事项

  • 在对指针取内容之前,一定要确保指针指在了合法的位置,否则将会导致程序出现不可预知的错误
  • 同级指针之间才能相互赋值,跨级赋值将会导致编译器报错或警告,通过&和*可以把变量变为同级指针

指针在嵌入式中的应用

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

#include<stdio.h>
int findmax(int* p, int nlength);
int main()
{
    int a[6] = { 12,34,52,74,42,212 };
    int max;
    findmax(&a,6);
    max= findmax(&a, 6);
    printf("%d", max);
}

int findmax(int* p, int nlength)
{
    int max;
    int i;
    max = p[0];
    for (i = 1; i < nlength; i++)
    {
        if (max < p[i])
        {
            max = p[i];
        }
    }
    return max;
}
    • 缺点是原变量的值容易被改变,可以加个const修饰
    • 使用指针传递输出参数,利用主函数和子函数使用同一套数据的特性,实现数据的返回,可实现多返回值函数的设计。不是return,而是通过指针修改主函数中的变量,以达到多个返回值的效果
//指针传递参数:实现多返回值
#include<stdio.h>

void Find_Max_Count(int *Max,int *Count,const int *array, int *nlength)
{
    int i;
    *Max=array[0];  //形参里的*Max,即实参里的&max,即*Max=*&max=max,所以最终为:max=array[0]
    *Count = 1;        //形参*Count=实参count=1
    for (i = 1; i < nlength; i++)
    {
        if (*Max < array[i])
        {
            *Max = array[i];
            *Count = 1;
        }
        else if (array[i]==*Max)
        {
            (*Count)++;
        }
    }
}

int main()
{
    int a[6] = { 12,13,11,14,14,14 };
    int max;
    int count;
    Find_Max_Count(&max, &count,a,6);

    printf("max=%d\n", max);
    printf("count=%d\n",count);

}
  • 传递返回值
    • 将模块内的公有部分返回,让主函数持有模块的“句柄”,便于程序对指定对象的操作
//指针:传递返回值,将模块内的公有部分返回,让主函数持有模块的“句柄”,便于程序对指定对象的操作

#include<stdio.h>


int Time[] = {23,11,12};//假设有个封装文件里,里面有个Time

int *Get_time(void) //返回值是一个int *型,即int型的指针
{
    return Time;
}


void main()
{
    int* p;
    p = Get_time(); //p也指向了Time

    printf("time[0]=%d\n", p[0]);
    printf("time[1]=%d\n", p[1]);
    printf("time[2]=%d\n", p[2]);

}
    • 注意的是,不能返回局部变量的指针,比如Time得是全局变量,如果是某个子函数中的局部变量,而局部变量在函数结束之后就会被销毁,所以虽然能访问到那个地址,但其实也是没用的
  • 直接访问物理地址下的数据(与单片机结合使用,比如获取某外设的ID)
    • 访问硬件指定内存下的数据,如设备ID号等
    • 将复杂格式的数据转换为字节,方便通信与存储
  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值