2

我有一个链接器符号(我们称之为 __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...*/
    /* ... */
}

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...*/
    /* ... */
}

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

谢谢。

4

1 回答 1

3

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

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

所以

unsigned long Val = *((unsigned long *) (__BASE_ADDR - 4));

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

extern unsigned char __BASE_ADDR[];

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

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

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

于 2013-04-22T15:29:27.993 回答