C++ 中的 C99 严格别名规则(海湾合作委员会)

发布于 2024-08-31 04:53:57 字数 313 浏览 8 评论 0原文

据我了解,GCC 在 C++ 中支持所有 C99 功能。但是 C99 严格别名在 C++ 代码中是如何处理的呢?

我知道在不相关的类型之间使用 C 类型转换不是严格别名安全的,并且可能会生成不正确的代码,但是 C++ 呢?由于严格别名不是 C++ 标准的一部分(正确吗?),GCC 必须指定语义本身。

我认为 const_caststatic_cast 在相关类型之间进行转换,因此它们是安全的,而 reinterpret_cast 可能会破坏严格的别名规则。

这是正确的理解吗?

As far as I understand, GCC supports all of its C99 features in C++. But how is C99 strict aliasing handled in C++ code?

I know that casting with C casts between unrelated types is not strict-aliasing-safe and may generate incorrect code, but what about C++? Since strict aliasing is not part of C++ standard (is that correct?), GCC must be specifying the semantics itself.

I figure const_cast and static_cast cast between related types, hence they are safe, while reinterpret_cast can break strict aliasing rules.

Is this a correct understanding?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤蝉 2024-09-07 04:53:57

不,你可能正在混合不同的东西。

严格的别名规则与 C99 标准完全无关。严格的别名规则植根于自[标准化]时代开始以来 C 和 C++ 中就存在的部分标准。 C89/90 (6.3) 和 C++98 (3.10/15) 中存在禁止通过另一种类型的左值访问一种类型的对象的子句)。这就是严格别名的全部内容,不多也不少。只是并非所有编译器都希望(或敢于)强制执行或依赖它。 C 和 C++ 语言有时都用作“高级汇编”语言,并且严格的别名规则通常会干扰这种使用。正是 GCC 做出了这一大胆的举动,并决定开始在优化中依赖严格的别名规则,这经常引起那些“汇编”类型的抱怨。

确实,在 C++ 中打破严格别名规则的最直接方法是reinterpret_cast(当然还有 C 风格的强制转换)。但是,static_cast 也可以用于此目的,因为它允许通过使用 void * 作为“链式”强制转换中的中间类型来打破严格别名

int *pi;
...
double *pd = static_cast<double *>(static_cast<void *>(pi));

。 const_cast 无法破坏兼容编译器中的严格别名。

至于C99...C99 确实引入了restrict 限定符。这与别名直接相关,但它本身并不是所谓的严格别名。

No, you are probably mixing different things.

Strict aliasing rules have absolutely nothing to do with C99 standard specifically. Strict aliasing rules are rooted in parts of the standard that were present in C and C++ since the beginning of [standardized] times. The clause that prohibits accessing object of one type through a lvalue of another type is present in C89/90 (6.3) as well as in C++98 (3.10/15). That's what strict aliasing is all about, no more, no less. It is just that not all compilers wanted (or dared) to enforce it or rely on it. Both C and C++ languages are sometimes used as "high-level assembly" languages and strict aliasing rules often interfere with such uses. It was GCC that made that bold move and decided to start relying on strict aliasing rules in optimizations, often drawing complaints from those "assembly" types.

It is true that the most straightforward way to break strict aliasing rules in C++ is reinterpret_cast (and C-style cast, of course). However, static_cast can also be used for that purpose, since it allows one to break strict aliasing by using void * as an intermediate type in a "chained" cast

int *pi;
...
double *pd = static_cast<double *>(static_cast<void *>(pi));

const_cast cannot break strict aliasing in a compliant compiler.

As for C99... What C99 did introduce was the restrict qualifier. This is directly related to aliasing, but it is not what is known as strict aliasing per se.

羁客 2024-09-07 04:53:57

static_cast 也可能违反别名规则,因为编译器相信您可以确保目标类型与对象的实际运行时类型相关。考虑:

extern void f(double*, int*); // compiler may optimize assuming that arguments don't overlap
double d;
void* pv = &d;
int* pi = static_cast<int*>(pv);
f(&d, pi); // assumption is violated

static_cast can break aliasing rules too, because the compiler is trusting you to ensure that the target type is related to the actual runtime type of the object. Consider:

extern void f(double*, int*); // compiler may optimize assuming that arguments don't overlap
double d;
void* pv = &d;
int* pi = static_cast<int*>(pv);
f(&d, pi); // assumption is violated
夜巴黎 2024-09-07 04:53:57

Cpp中的概念是一样的;因为您可以使用 C 风格的强制转换来指导您完成严格别名安全的操作。

简而言之:不,使用 Cpp 转换的方法(您已经概述的)并不能安全地涵盖所有情况。违反规则的一种常见方法是使用 static_cast 来转换指针。

只需打开编译器警告 - 它会(或者应该)告诉您什么是不安全的。

The concept is the same in Cpp; in that you can use C style casts to guide you through what is considered safe wrt strict aliasing.

In short: no, the approach to using Cpp casting (that you've outlined) will not safely cover all cases. One common way to break the rules is to use static_cast to cast pointers.

Just turn up the compiler warnings -- it will (or, should) tell you what is unsafe.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文