我在 C 文件中声明了一个数组 foo
,然后在相应的 header 中将其声明为 extern
。然后我从另一个文件访问 foo
,但是数组中第一个元素的地址是一个无效地址,并且与定义 foo
的编译单元中的地址不同。这是使用 ARM CodeSourcery 编译器从 Pebble SDK 构建的。
示例代码:
测试1.h
extern int foo[];
void testRoutine();
测试1.c
#include <pebble.h>
#include "test1.h"
void testRoutine()
{
APP_LOG(APP_LOG_LEVEL_INFO, "Hello World! foo: 0x%x", (unsigned int)&foo[0]);
}
int foo[] = {1,2,3,4,5,6};
主.c
#include <pebble.h>
#include "test1.h"
int main()
{
APP_LOG(APP_LOG_LEVEL_INFO, "Start of test");
testRoutine(); // Print the address of foo from the perspective of test1.c
APP_LOG(APP_LOG_LEVEL_INFO, "foo: 0x%x", (unsigned int)&foo[0]);
return 0;
}
预期输出:
Start of test
Hello World! foo: 0x12345678
foo: 0x12345678
实际输出:
Start of test
Hello World! foo: 0x20081234
foo: 0x21941234 (placeholders, I can't get the real addresses right now)
此代码在标准 x86 GCC 中按预期工作,但在 ARM 编译器上不起作用。是我弄乱了代码,还是这里有编译器错误?
最佳答案
我尝试在 Debian 64 位上重现您的问题但没有成功:
主要.c:
#include <stdio.h>
#include "test1.h"
int main()
{
testRoutine(); // Print the address of foo from the perspective of test1.c
printf("foo: 0x%x\n", (unsigned int)&foo[0]);
return 0;
}
测试1.h:
extern int foo[];
void testRoutine();
测试1.c:
#include <stdio.h>
#include "test1.h"
void testRoutine()
{
printf("Hello World! foo: 0x%x\n", (unsigned int)&foo[0]);
}
int foo[] = {1,2,3,4,5,6};
结果是:
$ ./program
Hello World! foo: 0x600970
foo: 0x600970
但是 gcc 警告是明确的:
test1.c:7:38: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
你应该试试:
APP_LOG(APP_LOG_LEVEL_INFO, "foo: 0x%p", &foo[0]);
编辑: 由于您说您在 32 位平台上运行它,其中 sizeof(unsigned int)==sizeof(int *),转换不是问题。您的程序中存在一些与此代码无关的其他问题(堆栈损坏?)。
关于c - 外部数组的地址在编译单元之间不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27212375/