将结构转换为整数合法吗?

huangapple go评论73阅读模式
英文:

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*)&amp;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

huangapple
  • 本文由 发表于 2023年6月22日 00:59:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76525588.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定