访问链接器变量时如何消除GCC的array-bounds警告
问题描述
我使用了如下链接器脚本片段:
.log_data : { PROVIDE(__start_log_section = .); KEEP(*(SORT(.log_section*))) PROVIDE(__stop_log_section = .); } > FLASH
对应的C代码如下:
extern void *__start_log_section; extern void *__stop_log_section; ... uint16_t byteAtOffset3 = *((uint16_t *)&__start_log_section + 3);
目前收到GCC警告:
array subscript 3 is outside array bounds of 'void[4]'...note: at offset 6 into object '__start_log_const_data' of size 4
我清楚GCC触发警告的原因——32位处理器下该变量大小为4字节,我的操作确实超出了变量本身的边界,但这正是链接器导出符号的正常使用方式。想请教:能否在不使用#pragma(无法在宏中使用)的前提下,抑制这类警告,或者让GCC识别此操作是合法的?
解决方案
修正链接器符号的声明类型
链接器导出的__start_log_section这类符号本质是内存地址标记,不是一个真正的指针变量,别声明成void*,改用数组类型声明:extern char __start_log_section[]; extern char __stop_log_section[]; ... uint16_t byteAtOffset3 = *((uint16_t*)(__start_log_section + 3));这种写法会让GCC将其视为一段内存区域的起始地址,而非固定大小的变量,后续的指针运算自然不会触发越界警告,也是最贴合链接器符号语义的写法。
也可以用标准库的
uintptr_t来处理地址,类型更严谨:#include <stdint.h> extern uintptr_t __start_log_section; ... uint16_t byteAtOffset3 = *((uint16_t*)((uintptr_t)&__start_log_section + 3));通过编译选项局部抑制警告
如果无法修改符号声明,可针对包含这段代码的文件,在编译时添加-Wno-array-bounds选项,关闭数组越界警告。但要注意,这个选项会关闭该文件内所有相关警告,可能漏掉真正的越界错误;如果想更精准,也可以把这段代码单独抽成一个小文件,只给这个文件加该编译选项。通过指针转换规避检查
把地址先转成void*再做运算,绕开GCC的数组边界检查逻辑:extern void *__start_log_section; ... uint16_t byteAtOffset3 = *((uint16_t*)((void*)&__start_log_section + 3));不过这种写法可读性较差,不如直接修正类型声明来得靠谱。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

