简体   繁体   English

指针和指针数组的联合是否保证单个指针与数组的第一个元素具有相同的地址?

[英]Does a union of a pointer and an array of pointers guarantee that the single pointer has the same address as the first element of the array?

With the struct:使用结构:

struct stree {
    union {
        void *ob;
        struct stree *strees[256];
    };
};

Do the C standards (particularly C11) guarantee that ob is an alias of stree[0] ? C 标准(尤其是 C11)是否保证obstree[0]的别名?

Maybe.也许。 The C standard only guarantees the following, 6.3.2.3: C 标准仅保证以下内容,6.3.2.3:

A pointer to void may be converted to or from a pointer to any object type.指向void的指针可以与指向任何对象类型的指针相互转换。 A pointer to any object type may be converted to a pointer to void and back again;指向任何对象类型的指针都可以转换为指向void的指针,然后再返回; the result shall compare equal to the original pointer.结果应与原始指针相等。

In theory/formally, a void* doesn't need to have the same memory representation as a pointer to object.理论上/形式上, void*不需要与指向对象的指针具有相同的内存表示。 Whenever it encounters such a conversion, it could in theory do some tricks like keeping track of the original value, to restore it later.每当遇到这样的转换时,理论上它可以做一些技巧,例如跟踪原始值,以便稍后恢复。

In practice, void* and object pointers have the same size and format on any sane system, because that's by far the easiest way to sate the above requirement.实际上, void*和对象指针在任何健全的系统上都具有相同的大小和格式,因为这是迄今为止满足上述要求的最简单方法。 Systems with extended addressing modes for objects exist, but they don't work as the C standard intended.存在具有对象扩展寻址模式的系统,但它们不能按照 C 标准的预期工作。 Instead they use non-standard extensions by inventing near and far pointer qualifiers, which could then be applied either to void* or an object pointer.相反,他们通过发明nearfar指针限定符来使用非标准扩展,然后可以将其应用于void*或对象指针。 (Some examples of this are low-end microcontrollers and old MS DOS.) (这方面的一些例子是低端微控制器和旧的 MS DOS。)

Bottom line: designing for portability to insane or fictional systems is a huge waste of time.底线:设计可移植到疯狂或虚构的系统是一种巨大的时间浪费。 Toss in a static_assert(sizeof(void*) == sizeof(int*), "...") and that should be enough.加入static_assert(sizeof(void*) == sizeof(int*), "...")就足够了。 Because in practice you're not going to find a system with magical or mysterious void* format.因为在实践中,您不会找到具有神奇或神秘void*格式的系统。 If you do, deal with it then.如果你这样做了,那就处理它。

What you have to keep in mind though, is that void* in itself is a different type, so you can't generally access the memory where the void* is stored through another pointer type (strict pointer aliasing).不过,您必须记住的是, void*本身是一种不同的类型,因此您通常无法通过另一种指针类型(严格指针别名)访问存储void*的内存。 But there are a few exceptions to the strict aliasing rule, type punning through unions is one of them.但是严格的别名规则有一些例外,通过联合进行类型双关就是其中之一。

So regarding your union , the void* and the first object pointer are guaranteed to be allocated starting at the same address, but again their respective sizes an internal formats could in theory be different.因此,关于您的unionvoid*和第一个对象指针保证从同一地址开始分配,但它们各自的大小和内部格式理论上可能不同。 In practice you can assume that they are the same, and because you use a union you aren't breaking strict aliasing.在实践中,您可以假设它们是相同的,并且因为您使用了union ,所以您不会破坏严格的别名。

As for best practice, it is to avoid void* in the first place, as there's very few places where you actually need them.至于最佳实践,首先要避免void* ,因为您真正需要它们的地方很少。 For the few cases where you need to pass some generic pointer around, it is often better to use uintptr_t and store the result as an integer.对于需要传递一些通用指针的少数情况,通常最好使用uintptr_t并将结果存储为整数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM