You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 19:36:03