访问 C 中链接器定义的符号

tw3*_*124 4 c linker symbols extern

我有一个链接器符号(我们称之为 __BASE_ADDR),在链接器命令脚本中定义,其中包含我需要使用的长字后面的长字的地址(例如,我需要检查地址 0x0000000C 处的长字,并且 __BASE_ADDR 等于 0x00000010 )。因此,在代码中我尝试使用 __BASE_ADDR 并从中减去 4 以访问 0x0000000C。

我的链接器映射输出正确显示 __BASE_ADDR 的值为 0x00000010。但是,当我尝试使用以下 C 代码访问该位置时,它不起作用:

extern unsigned char *__BASE_ADDR;

void someFunc( void )
{
    unsigned long Val = *((unsigned long *) (__BASE_ADDR - 4));

    /* Use Val for some comparison...*/
    /* ... */
}
Run Code Online (Sandbox Code Playgroud)

Val 设置为错误的值。似乎发生的情况是,无论 __BASE_ADDR 处的长字是什么,都将被视为地址,减去 4,并将所得地址的内容放入 Val 中。

但是当我执行以下操作时,它确实工作正常,并且 Val 被正确设置为地址 0x0000000C 处的任何内容:

extern unsigned char __BASE_ADDR[];

void someFunc( void )
{
    unsigned long Val = *((unsigned long *) (__BASE_ADDR - 4));

    /* Use Val for some comparison...*/
    /* ... */
}
Run Code Online (Sandbox Code Playgroud)

谁能阐明这一点?我理解为什么无法访问链接器符号的内容(从技术上讲它没有内容),但是为什么将链接器符号作为指针访问和作为数组访问之间会有区别?

谢谢。

Dan*_*her 5

(例如我需要检查地址处的长字0x0000000C并且__BASE_ADDR等于0x00000010

症状说的0x00000010不是__BASE_ADDR而是地址

所以

unsigned long Val = *((unsigned long *) (__BASE_ADDR - 4));
Run Code Online (Sandbox Code Playgroud)

确实读取了 处的值0x00000010(获取 的值),从中减去 4 并将结果解释为要存储在 中__BASE_ADDR的地址。unsigned longval

extern unsigned char __BASE_ADDR[];
Run Code Online (Sandbox Code Playgroud)

数组的地址__BASEADDR与数组第一个元素的地址相同,因此在这种情况下,

unsigned long Val = *((unsigned long *) (__BASE_ADDR - 4));
Run Code Online (Sandbox Code Playgroud)
  • 将数组名称转换__BASE_ADDR为指向其第一个元素的指针,结果的地址是__BASE_ADDR(只是不同类型)的地址0x00000010
  • 然后从中减去 4 unsigned char*,得到地址0x0000000C
  • 然后该地址被转换为unsigned long*,取消引用,并将位于该处的值存储在 中val

(最后一点很可能会调用未定义的行为,但如果您处理固定地址,您可能会处于知道它有效的情况。)