我正在尝试链接静态定义的结构数组。我正在使用extern修饰符来这样做。当我打印出我的extern结构的内存地址时,它与它在可执行文件中的位置不同。
这就是我所拥有的:
type.h:
typedef struct tableEntry {
const char *my_str;
void *my_addr;
int myint;
} my_struct;
test.c的:
include "type.h"
my_struct my_array[] = {
{"hello", (void*)15, 5000},
{"world", (void*)15, 3000},
{"abtest", (void*)15, 2000},
};
main.c中:
#include <stdio.h>
#include "type.h"
extern my_struct* my_array;
int main() {
printf("array location - %p\n", my_array);
printf("array entry 1 myint - %d\n", my_array[0].myint);
printf("array entry 1 address - %p\n", my_array[0].my_addr);
printf("array string location - %p\n", &(my_array[0].my_str));
printf("array string - %s\n", my_array[0].my_str);
}
我像这样编译程序:
gcc test.c main.c
当我运行我的可执行文件时,我得到以下输出:
array location - 0x4006be
array entry 1 myint - 29811
array entry 1 address - 0x6574626100646c72
array string location - 0x4006be
Segmentation fault (core dumped)
my_array在nm输出中的地址:
0000000000601060 D my_array
正如您所看到的,我的输出不是我所期望的,并且my_array没有正确链接(nm输出中的位置与实际程序打印的位置不同)。
注意:我不能在main.c中包含test.c文件。必须联系起来。
答案 0 :(得分:3)
更改
extern my_struct* my_array;
到
extern my_struct my_array[];
您无法使用extern
将数组修改为指针。
答案 1 :(得分:3)
my_array地址的问题是您打印值指针包含。但对于数组,您需要指针本身的地址(这将是数组的第一个元素的地址)。但是,作为指针,仍然会错误地声明(想知道为什么编译器不会抱怨)。
短:
为了获得相同的p,你实际上必须采用&p
,但这将是指向指针的类型指针,而不是结构。这是数组和指针之间的差异之一。有关详细信息,请阅读standard。
因此,请使用main.c
中实现文件中使用的相同声明。实际上,您应该将声明打包到标题type.h
中(请注意,这很容易与标准标题type**s**.h
混淆)。当你编译'type.c`时,这也会产生关于声明和定义不匹配的警告。这实际上是标题最重要的用途之一。
对于实际地址与逻辑地址nm
报告之间的差异:文件在执行前加载到RAM中,必须是根据加载地址重新定位。文件中的地址实际上是相对于.data
(初始化变量)或.bss
(未初始化,默认为0变量)部分的基址,对于文件中的每个部分通常为0。加载后,RAM中的起始地址将添加到这些相对地址以获取实际地址。这是程序在加载后可能需要一些时间的原因之一(重定位可能非常复杂)。
有一个例外:如果让链接器将程序重定位到绝对地址,例如裸机(没有完全成熟的OS)嵌入式控制器,nm
将报告与运行期间相同的地址-time或在调试器中。原因是链接器实际上包含上述运行时加载器的作业。结果,代码必须加载到正确的地址范围,例如,到闪存。