gpt4 book ai didi

c - 如何可靠地创建一个标记对象结束的符号?

转载 作者:行者123 更新时间:2023-11-30 19:30:05 24 4
gpt4 key购买 nike

我正在开发一个项目,我需要用 C 创建许多全局变量的地址范围(C++ 不可能),使用 clang。对于完整类型的符号,这通过符合标准的方式很容易:

typedef struct range {
void* begin;
void* end;
} range;

extern int foo;
range foo_range = { &(&foo)[0], &(&foo)[1] };

但正如我所说,它之所以有效,是因为 C 编译器静态地知道 foo 的大小,因此它能够将 &(&foo)[1] 解析为 foo+ 4 个字节(当然,假设 sizeof(int) 为 4)。这不适用于不完整类型的符号:

struct incomplete;
struct trailing_array {
int count;
int elements[];
};

extern int foo[];
extern struct incomplete bar;
extern struct trailing_array baz;

range foo_range = { &(&foo)[0], &(&foo)[1] };
// error: foo has incomplete type

range bar_range = { &(&bar)[0], &(&bar)[1] };
// error: bar has incomplete type

range bar_range = { &(&baz)[0], &(&baz)[1] };
// this one compiles, but the range excludes the elements array

不过,对我来说再多描述一下这些符号并不是问题。例如,我可以轻松添加元数据:

// foo.h
extern int foo[];
extern size_t foo_size;

// foo.c
int foo[] = {1,2,3};
size_t foo_size = sizeof(foo);

除了这对解决 foo.c 之外的引用问题没有帮助,因为 foo_size 不是编译时常量,因此这不会工作:

range foo_range = { &foo, (void*)&foo + foo_size };
// error: foo_size not a compile-time constant

然而,有效的方法是获取在我的对象结束处结束的符号的地址。例如,如果我使用以下汇编代码定义 foo:

_foo:
.long 1
.long 2
.long 3
_foo_end:

然后,在我的 C 代码中,我可以:

extern int foo[];
extern int foo_end;
range foo_range = { &foo, &foo_end };

这有效地解决了我的问题。

但是,虽然我可以灵活地添加符号,但我无法灵活地将每个全局声明重写为文件级汇编语句。所以,我的问题是:使用 clang 能达到的最接近的结果是什么?

  • 我知道我可以使用节(因为链接器为节创建开始和结束符号),但每个全局变量一个节就太过分了。
  • 我知道我不能只在想要获取其范围的全局变量之后直接获取变量的地址,因为已知编译器在某些情况下会对全局变量重新排序。<

我专门使用 Apple 的链接器,但如果您有适用于 GNU ld/gold 或 lld 的解决方案,我仍然会采用它,看看是否也可以让它在这里工作。

最佳答案

嗯,如果您在另一个翻译单元中定义它,则没有真正的方法可以做到这一点。如果需要,您可以添加 types.h包含内容的文件

struct incomplete {
char data[SIZE];
}

其中 SIZE 是您喜欢的任何整数,并对每个全局变量执行相同的操作。然而,这将与 future 的定义相交叉。真的,你必须去

#define INCOMPLETE_SIZE 5

然后将其用于 range = { &bar, (void*)&bar + INCOMPLETE_SIZE } .

“不完整类型”只是一些标准术语,用于正确描述如何解析

struct A {
A* ptr;
}

据我所知,除此之外它们并没有真正被使用。

我也不推荐&(&foo)[0], &(&foo)[1]作为获取一系列指针的方法,它非常深奥/难以阅读。更优选的是&foo, &foo + 1 。您可以看到如何将其转变为 bar 的解决方案。通过这样做&bar, (void*)&bar + SIZE ,其中 SIZE 是您必须在代码中的某个位置指定的某个常量(通过声明它并使用 sizeof/&foo+1 解决方案,或者使用 SIZE 定义 #define )

关于c - 如何可靠地创建一个标记对象结束的符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51661078/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com