【问题标题】:Accessing linker defined symbol in C在 C 中访问链接器定义的符号
【发布时间】:2013-04-15 13:48:53
【问题描述】:

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

有人能解释一下吗?我理解为什么您不能访问链接器符号的内容(从技术上讲,它没有内容),但是为什么将链接器符号作为指针访问和作为数组访问会有区别呢?

谢谢。

【问题讨论】:

    标签: c linker extern symbols


    【解决方案1】:

    (例如,我需要检查地址 0x0000000C 的 longword 和 __BASE_ADDR 是否等于 0x00000010

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

    所以

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

    确实读取了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
    • 然后从unsigned char* 中减去4,得到地址0x0000000C
    • 然后将该地址转换为unsigned long*,取消引用,并将位于那里的值存储在val中。

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

    【讨论】:

    • 我的错,这实际上是一个错字 - extern 实际上是代码中的一个字符!
    • 更改了答案以解决当前情况。
    • 您的猜测是正确的,链接器符号实际上是地址的名称。因此,当您在链接器文件中写入 X = 5 时,您实际上是在说 X 是地址 5 的名称。因此,在 C 代码中,如果您想从 X 中提取值 5,您必须将 X 声明为符合这些语义。
    猜你喜欢
    • 1970-01-01
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多