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

时间:2013-04-22 15:27:14

标签: c linker extern symbols

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

任何人都可以对此有所了解吗?我明白为什么你不能访问链接器符号的内容(技术上没有内容),但为什么在将链接器符号作为指针访问并将其作为数组访问之间会有区别?

感谢。

1 个答案:

答案 0 :(得分:2)

  

(例如,我需要检查地址0x0000000C上的长字以及__BASE_ADDR等于0x00000010

症状表明0x00000010不是__BASE_ADDR,而是地址

所以

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

确实读取0x00000010处的值(获取__BASE_ADDR的值),从中减去4并将结果解释为unsigned long的地址以存储在{{1}中}}

使用

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*中。

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