英文:
Is casting a struct to an integer legal?
问题
struct test {
int num;
};
int main() {
struct test t = {1234};
int n = *((int*)&t); // n = 1234
return 0;
}
上面的代码片段是否合法且不会导致未定义行为?我在生产中看到了类似的代码片段。
编辑:请原谅此处使用了C风格的转换。
<details>
<summary>英文:</summary>
struct test{
int num;
};
int main(){
struct test t = {1234};
int n = ((int)&t); // n = 1234
return 0;
}
Is the above snippet legal and causes no undefined behavior? I have seen [this similar code snippet][1] in production.
Edit: Please forgive the C style cast being used here.
[1]: https://github.com/v8/v8/blob/49ca43f9cc4423dfbbf615fb92856d2d1b5a3ab6/src/snapshot/read-only-serializer-deserializer.h#L109
</details>
# 答案1
**得分**: 4
结构体
```cpp
struct test {
int num;
};
是一个标准布局结构体。可以保证结构体 test 中的数据成员 num 在零偏移处。
标准布局结构体对于与其他编程语言编写的代码进行通信非常有用,例如在 C 中。
在 C 中,结构体类型的对象的地址等于其第一个数据成员的地址。
根据 C 标准 (6.7.2.1 结构体和联合体说明符)
15 在结构体对象内部,非位字段成员和位字段所在的单元的地址按照它们声明的顺序增加。适当转换的结构体对象指针指向其初始成员(或者如果该成员是位字段,则指向其中所在的单元),反之亦然。结构体对象内部可能存在未命名的填充,但不在其开头。
因此,这段代码
int n = *((int*)&t);
是有效且合法的。
与 C 强制转换不同,最好使用 C++ 的 reinterpret_cast 强制转换。
正如 @HolyBlackCat 在他的评论中指出的(例如 C++ 20 标准,6.8.3 复合类型)
4 两个对象 a 和 b 如果可以互相指针转换,那么它们具有相同的地址,并且可以通过
reinterpret_cast从一个指针获得另一个指针
请注意,这只返回了要求的翻译部分,不包含其他内容。
英文:
The structure
struct test{
int num;
};
is a standard layout structure. It is guaranteed that its data member num is at zero offset in the structure test.
Standard layout structures are useful for communicating with code written in other programming languages as for example in C.
In C the address of an object of a structure type is equal to the address of its first data member.
From the C Standard (6.7.2.1 Structure and union specifiers)
> 15 Within a structure object, the non-bit-field members and the units
> in which bit-fields reside have addresses that increase in the order
> in which they are declared. A pointer to a structure object,
> suitably converted, points to its initial member (or if that member
> is a bit-field, then to the unit in which it resides), and vice versa.
> There may be unnamed padding within a structure object, but not at its
> beginning.
So this code snippet
int n = *((int*)&t);
is valid and well-formed.
Instead of the C casting it is better to use the C++ casting reinterpret_cast.
As @HolyBlackCat pointed to in his comment (For example the C++ 20 Standard, 6.8.3 Compound types)
> 4 Two objects a and b are pointer-interconvertible if:
>
> //...
>
> (4.3) — one is a standard-layout class object and the other is the
> first non-static data member of that object, or, if the object has no
> non-static data members, any base class subobject of that object
> (11.4), or
>
> //...
>
> If two objects are pointer-interconvertible, then they have the same
> address, and it is possible to obtain a pointer to one from a pointer
> to the other via a reinterpret_cast
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论