英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论