【发布时间】:2021-12-03 00:09:41
【问题描述】:
我将相对指针定义为Ginger Bill describes as Self-Relative Pointers:
... 将 [偏移量将应用到的] 定义为偏移量本身的内存地址
例如,考虑这个结构:
struct house {
int32_t weight;
}
struct person {
int32_t age;
struct house* residence;
}
int32_t getPersonsHousesWeight(struct person* p) {
return p->residence->weight;
}
我认为可能可行的 C 语言中相同事物的相对指针实现是:
struct house { ... } // same as before
struct person {
int32_t age;
int64_t residence; // an offset from the person's address in memory
}
int32_t getPersonsHousesWeight(struct person* p) {
return ((struct residence*)((char*)p + (p->residence)))->weight;
}
假设一切都对齐良好(全部 8 个字节),这是否没有未定义的行为?
编辑
@tstanisl 提供了一个很好的答案(我已经接受了),它在堆栈分配的上下文中彻底解释了 UB。我很好奇分配到一大块连续堆中会如何影响这个分析。例如:
int foo(void) {
char* base = mmap(NULL,4096,PROT_WRITE | PROT_READ,-1,MAP_PRIVATE | MAP_ANONYMOUS);
// Omitting mmap error checking
struct person* myPerson = (struct person*)(base + 128);
struct house* myHouse = (struct house*)(base + 256);
int32_t delta = (char*)myHouse - (char*)myPerson;
// Does the computation of delta invoke UB?
}
【问题讨论】:
-
对我来说,这取决于你如何定义偏移量,如果你在运行时设置它像
p->residence = (intptr_t)p - (intptr_t)h(假设person* p,house* h)那么它会很好用。 -
这取决于
p和struct house对象是否属于同一个大对象,例如struct person_in_da_house { struct person p; struct house h; }。另外,指针p是如何构造的还有一些技术条件。
标签: c