19

私の知る限り、GCC は C++ で C99 のすべての機能をサポートしています。しかし、C99 の厳密なエイリアシングは C++ コードでどのように処理されるのでしょうか?

関係のない型間での C キャストによるキャストは厳密なエイリアシングセーフではなく、誤ったコードを生成する可能性があることは知っていますが、C++ はどうでしょうか? 厳密なエイリアシングは C++ 標準の一部ではないため (正しいですか?)、GCC はセマンティクス自体を指定する必要があります。

const_cast関連する型間で計算してstatic_castキャストするため、それらは安全ですが、厳密なreinterpret_castエイリアシング規則に違反する可能性があります。

これは正しい理解ですか?

4

3 に答える 3

33

いいえ、おそらく異なるものを混ぜています。

厳密なエイリアシング ルールは、特に 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修飾子でした。これはエイリアシングに直接関連していますが、それ自体は厳密なエイリアシングとして知られているものではありません。

于 2010-05-05T06:30:24.907 に答える
4

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
于 2010-05-05T06:30:52.753 に答える
2

コンセプトは Cpp でも同じです。Cスタイルのキャストを使用して、厳密なエイリアシングに関して安全と見なされるものをガイドできるという点で。

要するに、いいえ、Cpp キャストを使用するアプローチ (概説したもの) は、すべてのケースを安全にカバーするわけではありません。ルールを破る一般的な方法の 1 つは、static_cast を使用してポインターをキャストすることです。

コンパイラの警告を表示するだけで、何が危険かがわかります(または、そうすべきです)。

于 2010-05-05T06:35:21.080 に答える