嵌入式-C语言-6-指针

一、指针(C语言灵魂)

1.1.指针的定义:指针本质就是一个变量,而这个变量永远只能存储一个内存地址(编号)所以此变量对应的专业术语叫指针变量,通过指针变量保存的地址就可以对这块内存区域任意访问(读查看,写修改),而指针指向的内存区域可以保存一个数字,而这个数字有数据类型

1.2.指针变量定义的语法格式:

a)书写形式1:

int  *  变量名;

例如:int * pa; //定义一个指针变量

b)书写形式2:

int*  变量名;

例如:int* pa; //定义一个指针变量

c)书写形式3:

int  *pa; //定义一个指针变量

语义:都是定义一个指针变量,将来这个变量pa能够保存一块内存区域的首地址,并且这块内存区域保存着一个int类型的数据,由于指针变量也是变量,同样需要分配内存空间

          问:指针变量占用多大的内存空间呢?

          答:得看保存的地址有多大,这个跟计算机硬件相关

32位系统,一个地址值32位,4字节

64位系统,一个地址值64位,8字节

结论:指针变量分配的内存空间为4字节或者8字节,所以指针变量本身没有数据类型,只是它指向的内存区域保存的数字有数据类型,所以int不是给指针变量用,而是给指针变量指向的内存区域保存的数字用的

d)连续定义指针变量形式:

    int *pa, *pb; //定义两个指针变量

    int *pa, pb; //pa是指针变量,而pb就是一个普通的int类型变量

e)切记:定义指针变量后如果不初始化,此指针变量保存的一个地址值是随机的,也就是此指针变量指向任意内存区域,相当危险,因为此块内存区域,不是操作系统合法给你分配的内存,此指针变量为野指针!

1.3.指针变量初始化通过取地址&来进行:

      int  a = 250; //分配4字节内存空间,存储250数字,而这个数字类型为int类型

      int *pa = &a; //定义一个指针变量,也就是分配一个4字节内存空间(前提是32位)

     保存变量a对应的内存空间的首地址,俗称pa指向a

     问:一旦通过指针变量来获取到指向的内存区域的首地址,如何通过指针变量,对指向的内存区域进行操作,也就是对指向的内存区域进行读查看或者写修改呢?

     答:通过解引用运算符:*

1.4.解引用运算符(又称取目标运算符):*

      功能:就是通过指针变量对指向的内存区域进行读查看或者写修改

      语法格式:*指针变量 = 取目标

      例如:

      char a = 100;

      char *pa = &a;  

      或者:

      char a = 100;

      char *pa = NULL;

      pa = &a;

      //打印pa指向a的内存数据

      printf("%d\n", *pa);   //100

     //修改pa指向a的内存数据

     *pa = 10; //结果是变量a的内存由原来的100变成10

     结论:sizeof(指针变量名) = 4(永远的)

1.5.特殊指针:空指针和野指针

a)空指针:空指针变量保存一个空地址,用NULL表示,其实就是编号为0地址

空指针不可以随意访问,否则造成程序的崩溃!

例如:

int *pa = NULL;

printf("pa指向的0地址保存的数据为%#x\n", *pa);

*pa = 250; //向0地址写入数据250

b)野指针:没有初始化的指针变量,它保存着一个随机地址,指向着一块无效的内存,因为这块内存区操作系统并没有给你分配,如果对野指针进行非法访问,也会造成程序的崩溃!

int *pa; //pa就是野指针       

           printf("pa指向的0地址保存的数据为%#x\n", *pa);

*pa = 250; //向0地址写入数据250

c)切记:实际开发代码的编程规范

   如果定义一个指针变量,一开始不清楚它到底指向谁,千万不能不初始化,否则变成了野指针所以此时要求初始化为空指针NULL,一旦初始化为NULL,将来程序后面使用时,要记得对指针变量进行安全的判断,判断它是否为NULL,如果为NULL,让程序结束或者函数返回,如果为有效地址,程序才能继续通过指针变量进行操作

   例如:

  int *pa; //不建议这么写,危险
   //安全做法:
   int *pa = NULL; //赋值为空指针
   if(NULL == pa) {
printf("pa指向空指针,不能继续访问.\n");
return -1 或者exit(0); //函数返回或者程序退出
   } else {
        printf("pa指向一块有效内存,可以继续访问\n");
        printf("%d\n", *pa);
        *pa = 250;
   }  
   //安全做法:
   int *pa = NULL; //赋值为空指针
   int a = 250;
   pa = &a; //让pa指向a
   if(NULL == pa) {
printf("pa指向空指针,不能继续访问.\n");
return -1 或者exit(0); //函数返回或者程序退出
   } else {
        printf("pa指向一块有效内存,可以继续访问\n");
        printf("%d\n", *pa);
        *pa = 251;
   }

1.6.指针运算

a)指针可以和一个整数做加减法运算,简称地址运算

   切记:计算结果和指针指向的变量数据类型有关系

b)指针计算公式:

   1.char型指针+1,表示实际地址+1

      例如:

      char *pa = 0x1000; //假设pa指向0x1000

      pa++; //pa=0x1001

   2.short型指针+1,表示实际地址+2

      short *pa = 0x1000; //假设pa指向0x1000

      pa++; //pa=0x1002

   3.int/long型指针+1,表示实际地址+4

      long *pa = 0x1000; //假设pa指向0x1000

      pa++; //pa=0x1004

1.7.指针和数组的那点事儿(之前都是研究指针和变量的那点事儿)

a)回顾数组相关内容

   定义数组:int a[4] = {'A', 'B', 'C', 'D'};

   结论:

   1.数组名就是数组的首地址,同样遵循指针的运算公式

   2.&a[2]就是第2个元素的首地址

   3.a+2也是第2个元素的首地址 

   4.&a[2] - a = a + 2 - a = 2个元素,表示第2个元素和第0个元素之间差2个元素,实际的地址差8个字节=2个元素*int

   5.目标:a,&a[2],a+2都是地址,干脆定义一个指针变量保存数组的首地址,将来利用指针变量和指针变量的计算公式很轻松即可访问元素

b)指针和数组关系公式:

   int a[4] = {1,2,3,4,5};

   int *pa = a; //定义指针变量保存整个数组的首地址

1.指针和数组的写法1:

   //查看所有元素的值:
   for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
printf("%d\n", *(p+i));
   //将所有元素乘10倍
  for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
*(p+i) *= 10;

2.指针和数组的写法2:  

 int len = sizeof(a)/sizeof(a[0]) ; //求数组的内存空间大小
   //查看所有元素的值:
   for(pa = a; pa < a + len; p++)
printf("%d\n", *p);
   //将所有元素乘10倍
  for(pa = a; pa < a + len; )
*p++ *= 10; //*p++:先算*p,后做p++

3.指针和数组的写法3:

   //查看所有元素的值:
   for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
printf("%d\n", p[i]);
   //将所有元素乘10倍
  for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
p[i]  *= 10;

   切记:"[]"运算符要经过两步运算:

   例如:a[2]经过两步运算:

   1.先算地址:a + 2

   2.再取值:*(a+2)

   所以:p[2]经过两步运算;

   1.先算地址:p+2

   2.再取值:*(p+2)

c)终极获取元素值的公式: a[i] = p[i] = *(a+i) = *(p+i)

1.8.常量,常量指针,指针常量,常量指针常量:围绕关键const(笔试题必考)

a)常量定义:不可修改的值,例如:250,'A'等

b)const关键字功能:常量化,四种形式:

1.const可以修饰普通变量,一旦修饰该变量就会被当成常量处理,即其值一经初始化再也不能改

   例如:

   const int a = 250;

   a = 200; //gcc编译时会报错

2.常量指针:不能通过指针变量来修改指向的内存区域的值(保护内存区域不可乱改)

   例如:

   int a = 250;

   const int *p = &a; //定义初始化一个常量指针

   或者

   int const *p = &a; //定义初始化一个常量指针

   *p = 200; //gcc编译时会报错

   printf("%d\n", *p); //可以,仅仅是读查看

   或者

   int b = 300;

   p = &b; //可以,指针变量p本身是可以修改的,p此时指向b

   *p = 400; //gcc编译时会报错

   printf("%d\n", *p);//可以,仅仅是读查看

3.指针常量:指针永远指向一块内存区域,不能再指向别的地方(保护指针不可乱指向)

   例如:

   int a = 100;

   int* const p = &a;

   *p = 300; //可以,可以修改指向的内存区域

   int b = 200;

   p = &b; //不可以,gcc报错

  

4.const int * const p:常量指针常量,表示p本身不可修改,同时p指向的目标也不能修改只能通过p来查看内存区域的值

   例如:

   int a = 100;

   const int* const p = &a;

   *p = 300; //不可以,可以修改指向的内存区域

   int b = 200;

   p = &b; //不可以,gcc报错

   printf("%d\n", &p); //可以

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嵌入C语言中,指针是一个非常重要的概念。它允许我们直接访问内存中的数据,并有效地操作和传递数据。以下是一些嵌入C语言指针的常见用法: 1. 变量地址获取:可以使用指针获取变量在内存中的地址,通过在变量名前加上 '&' 符号来获取。例如,如果有一个整数变量 x,可以使用 int *ptr = &x; 来获取 x 的地址,并将其存储在指针变量 ptr 中。 2. 间接访问:通过指针,可以间接地访问和修改变量的值。例如,如果有一个指针变量 ptr 指向一个整数变量 x,可以使用 *ptr 来访问和修改 x 的值。例如,*ptr = 10; 将会把 x 的值修改为 10。 3. 动态内存分配:在嵌入系统中,内存资源通常是有限的。使用指针,我们可以在运行时动态地分配和释放内存。通过使用函数如 malloc() 和 free(),可以分配和释放堆内存。例如,int *ptr = (int *)malloc(sizeof(int)); 可以动态地分配一个整数大小的内存块,并将其地址存储在指针变量 ptr 中。 4. 数组访问:指针也可以用于访问数组元素。数组名本身就是一个指向数组首元素的指针。可以通过指针进行数组元素的访问和操作。例如,int arr[5]; int *ptr = arr; 可以将数组 arr 的首地址存储在指针变量 ptr 中,并通过指针操作数组元素。 5. 函数指针:在嵌入系统中,函数指针是一种常见的用法。通过函数指针,可以动态地调用不同的函数。例如,定义一个函数指针变量 int (*funcPtr)(int, int); ,然后将其指向不同的函数,可以在运行时决定调用哪个函数。 这些只是嵌入C语言指针的一些常见用法,它们在嵌入系统开发中非常重要。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值