PIC32平台访问unsigned char字体数组时出现指针非法访问异常
问题核心原因
1. 架构对齐限制
绝大多数嵌入式处理器(如ARM Cortex-M、RISC-V嵌入式配置等)要求多字节基础类型的访问地址必须对齐到类型自身大小:int通常为4字节,因此访问地址必须是4的整数倍,否则会触发硬件非法访问异常。而你测试用的在线C编译器一般运行在x86/x86_64架构,该架构默认支持非对齐访问仅会损失性能,不会抛出异常,因此第一种写法在线测试正常。
2. 两种写法的地址差异
- 第一种写法中
ptr是全局变量,初始化时指向const unsigned char类型的font数组:unsigned char是单字节类型,编译器默认不会给该数组加4字节对齐属性,链接时font数组可能被分配到非4对齐的地址,ptr指向的地址天然非对齐,强转int*解引用直接触发异常。 - 第二种写法在函数作用域内给
ptr赋值,部分编译器在函数内对局部指针赋值做了隐式对齐优化,或是当前上下文下font地址刚好对齐,因此可以临时运行,但本质仍然是未定义行为,后续修改代码/调整编译参数仍有概率出错。
3. C标准的未定义行为
将指向低宽度类型的指针强制转换为高宽度类型指针并直接解引用,本身就属于C标准规定的未定义行为,执行结果完全由处理器架构、编译器实现、链接规则决定,没有可移植性。
修复方案
如果你要保留第一种写法的全局指针结构,可使用以下任意方案修复:
- 给
font数组强制添加4字节对齐属性,保证数组起始地址对齐:
// GCC/Clang 写法 const unsigned char font[] __attribute__((aligned(4))) = {...}; // Keil MDK 写法 const unsigned char __align(4) font[] = {...};
- 避免直接强转指针解引用,用
memcpy拷贝数据,完全规避对齐问题,可移植性最高:
#include <string.h> void lcd_map(){ int val; memcpy(&val, ptr, sizeof(val)); }
- 手动按字节拼接
int值,还可自由控制大小端顺序:
void lcd_map(){ // 小端模式拼接,若为大端调整字节顺序即可 int val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); }
内容的提问来源于stack exchange,提问作者Bruno Leppe
相关产品推荐
相关产品推荐

