GCC无绝对寻址场景下如何实现两变量共享同地址直接访问
GCC下实现同地址双变量直接访问的方案
GCC原生支持这类共享内存的多别名访问特性,不需要绝对寻址类扩展,可按以下方式实现:
推荐实现(适配主流版本)
该方案依赖C11标准的匿名联合特性,GCC 4.6及以上版本原生支持,默认编译(GNU方言模式,如gnu99/gnu11)下无需额外指定编译参数即可使用。
首先定义位域结构体,去掉IAR专属的编译器扩展关键字即可:
typedef struct { unsigned char no0:1; unsigned char no1:1; unsigned char no2:1; unsigned char no3:1; unsigned char no4:1; unsigned char no5:1; unsigned char no6:1; unsigned char no7:1; } __BITS8;
直接在全局/文件作用域定义匿名联合,用标准C的volatile关键字修饰即可,不需要IAR专属的__saddr、__no_init、@地址等非标准扩展:
volatile union { unsigned char P0; __BITS8 P0_bit; };
定义完成后使用方式和IAR环境完全一致:
P0 = 0x80; // 二者共享同一内存地址,修改任意一个另一个会同步变更 P0_bit.no7 == 1; // 该表达式返回值为真
注意:位域的位分配顺序和目标架构端序、ABI实现相关,在绝大多数嵌入式常用的小端架构(ARM、RISC-V、AVR等)下,上述定义中no0对应字节最低位、no7对应字节最高位,和IAR编译器行为一致;大端架构下建议先做简单测试确认位序匹配。
旧标准兼容实现(适配C89)
如果需要兼容不支持匿名联合的极老GCC版本、或强制使用C89标准编译,可以通过宏映射实现完全相同的效果,无额外运行时开销,编译生成的汇编代码和匿名联合方案完全一致:
/* 位域结构体定义和上述方案一致 */ typedef struct { unsigned char no0:1; unsigned char no1:1; unsigned char no2:1; unsigned char no3:1; unsigned char no4:1; unsigned char no5:1; unsigned char no6:1; unsigned char no7:1; } __BITS8; /* 定义实际的联合存储变量,static修饰避免跨文件符号冲突 */ static volatile union { unsigned char P0; __BITS8 P0_bit; } __p0_shadow; /* 宏映射为可直接访问的全局名称 */ #define P0 __p0_shadow.P0 #define P0_bit __p0_shadow.P0_bit
内容的提问来源于stack exchange,提问作者andz
相关产品推荐
相关产品推荐

