嵌入式中指针几个简单却常见的用法

本文介绍了使用C51进行绝对地址访问的几种方法,包括宏定义直接操作内存、定义指向特定地址的指针变量及通过函数传递指针进行处理等。同时,还讨论了指针在C51中的占用字节数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
 
用法一:绝对地址访问:
1.1:
#define XBYTE      ((unsigned char volatile xdata *) 0)
#define MDrv_WriteByte( u16Reg, u8Value )   (XBYTE[u16Reg] = u8Value)
 
1.2;
 #define FVAR(object, addr)   (*((object volatile xdata *) (addr)))
相当于定义了一个指针变量:  object volatile xdata *pPtr=&(addr),故可以直接再使用该指针了。可以FVAR(unsigned char , 0x8000)=10;unsigned char a=FVAR(unsigned char , 0x8000);
 
总结一句话,其实以上两个用法都来自于keil 的absacc.h 的原型。
 
1.3:
  void funName( dataType a ,unsigned char * pPtr)
 {
      for(i=0;i<sizeof(a);i++) 
      {
        pPtr[i]=i;   // 在这里只是表示了要对 *pPtr来进行处理。
      }
 }
 
void main(void)
{
   unsigned long a;
   funName(a,(unsigned char *)&a);
   //todo
   // 在此时你已经a按unsigned char 的字节数进行了处理。
 
}
 
当然了,以前说的几个都是很简单的、老生常谈的东西,再举一个我一次面试的关于指针的试题,很简单。
1.4
 
说出下列变量在c51占几个字节;
unsigned char *ptr; // 2 Bytes 按8bit c51
unsigned long *ptr   // 2 Bytes 按8bit c51
void * ptr;          // 一般是;2 Bytes 按8bit c51
void fun(unsigned char * param) // 2 Bytes 按8bit c51;
 
说的可能太简单了,没有必要再讲的再细了。
### 嵌入式开发中指针操作寄存器的方法 在嵌入式系统中,指针常被用来直接访问硬件寄存器。由于寄存器是位于硬件电路中的高速存储单元[^2],通过指针操作这些寄存器可以实现高效的硬件交互。 #### 定义指向寄存器的指针 为了安全有效地操作寄存器,通常会定义一个特定类型的指针来指向该寄存器地址。例如,在C语言中可以通过`volatile`关键字声明变量或指针,防止编译器优化影响实际硬件行为: ```c #define REG_ADDRESS ((volatile uint32_t *)0x40000000) // 使用指针对寄存器写入值 *REG_ADDRESS = 0xABCD; // 读取寄存器的值 uint32_t regValue = *REG_ADDRESS; ``` 这里使用了 `volatile` 关键字以确保每次访问都从真实的物理地址获取数据而不是缓存在CPU寄存器中[^2]。 #### 访问内存映射的寄存器 许多微控制器采用内存映射的方式将外设寄存器映射到系统的地址空间内。这意味着可以通过标准的指针运算符来访问这些寄存器。例如,假设某个UART模块有多个连续排列的功能配置寄存器,则可通过如下方式设置波特率分频器: ```c typedef struct { volatile uint32_t UART_DR; // 数据寄存器 volatile uint32_t UART_RSR; // 错误状态寄存器 volatile uint8_t RESERVED[4]; // 预留字段 volatile uint32_t UART_FR; // 标志位寄存器 } UART_Registers; #define UART_BASE (0x40001000UL) UART_Registers *uart_regs = (UART_Registers *)UART_BASE; // 设置波特率分频器 uart_regs->UART_BAUD_DIVIDER = 9600; ``` 这段代码展示了如何利用结构体和指针联合起来简化复杂外设寄存器组的操作过程[^2]。 #### 解决常见指针操作问题 尽管指针提供了强大的功能去操控底层资源,但也容易引发一些难以察觉的问题。以下是几个典型例子及其解决方案: - **未初始化指针**: 如果忘记给指针赋初值就尝试解引用它可能会导致不可预测的行为甚至崩溃。始终要确认任何使用的指针都已经正确定向至有效目标位置。 - **越界访问**: 当处理数组或者链表之类的动态分配对象时,超出其边界范围可能导致非法内存区域被修改进而破坏其他部分的数据一致性。务必小心计算索引偏移量并验证逻辑正确无误后再执行相应指令序列[^1]。 - **野指针释放后继续引用**: 动态创建的对象销毁之后如果仍然保留着原来的指针副本再去间接调用其中成员函数的话同样会造成严重后果。建议一旦完成清理工作立即将关联句柄置为空(NULL),以便后续检测是否存在此类隐患[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值