問題タブ [strict-aliasing]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - float ビットと厳密なエイリアシング
未定義の動作を呼び出さずに float からビットを抽出しようとしています。これが私の最初の試みです:
私が理解しているように、厳密なエイリアシング規則により、これが機能することは保証されていませんよね? 文字ポインターを使用して中間ステップを実行すると機能しますか?
または、個々のバイトを自分で抽出する必要がありますか?
もちろん、これにはエンディアンに依存するという欠点がありますが、私はそれを受け入れることができました.
ユニオンハックは間違いなく未定義の動作ですよね?
完全を期すために、ここに の参照バージョンを示しfoo
ます。また、未定義の動作ですよね?
それで、フロートからビットを抽出することは可能ですか(もちろん、両方が32ビット幅であると仮定します)?
編集: そして、これmemcpy
が Goz によって提案されたバージョンです。多くのコンパイラはまだサポートしていないため、いくつかのテンプレート メタプログラミングstatic_assert
に置き換えました。static_assert
c++ - この場合、メンバ変数へのポインタをキャストしても問題ありませんか?
私は最近、C++ の知識を更新/更新しており、厳密なエイリアシングについて学ぶことで、ある型のポインターを別の型にキャストすることに少し警戒するようになりました。次のコード サンプルが私のコンパイラで実際に機能することはわかっていますが、現在の標準に準拠していることを確認したいと思います。
基本的に、この単純なタプルには要素のペアが含まれており、各要素は共通の基本クラスから派生する必要があります。Get 関数は、Base*
指定されたインデックスが表すメンバーに を返します。
私が疑問に思っている重要な部分は、reinterpret_casts です。Derived Struct::*
to からto へのキャストBase Struct::*
は一般的に禁止されていることはわかっていますが、この場合は、ポインターからメンバーへの変数のみを使用して、オブジェクトへのポインターを取得します。(派生オブジェクトをベース オブジェクトであるかのようにコピーしたり、ベース オブジェクトを派生オブジェクトのメモリに詰め込もうとしたりしません。) これは G++ で意図したとおりに機能し、そうでないことを確認したいだけです。これを行うために、準拠しているコンパイラに噛まれます。
c++ - 変数の生のコピーを実行する単純なキャストは厳密なエイリアシングを壊しますか?
最近、厳密なエイリアシングについてよく読んでいます。a
C/C++ 標準では、次のコードは無効であると述べられています(未定義の動作が正しい) b
。
標準では、char*
何でもエイリアスできると述べているため、char*
変数への書き込みアクセスが行われるたびに、コンパイラーはキャッシュされたすべての値をリロードします。したがって、次のコードは正しいでしょう。
しかし、ポインターがまったく関与していない場合はどうでしょうか? たとえば、次のコードがあり、GCC は厳密なエイリアシングに関する警告をスローします。
私がやりたいのは、の生の値をコピーa
することだけなので、厳密なエイリアシングは適用されません。ここに問題がある可能性がありますか、それとも GCC がそれについて過度に用心深いだけですか?
編集
memcpyを使用した解決策があることは知っていますが、コードが読みにくくなるため、その解決策を使用したくありません。
EDIT2
int32_t b = *reinterpret_cast<int*>(&a);
も機能しません。
解決した
これはGCC のバグのようです。
c++ - -O2がある場合とない場合のシフト演算子の異なる動作
-O2がない場合、このコード84 84
は出力されます。O2フラグがある場合、出力は84 42
です。gcc 4.4.3.
コードは、64ビットLinuxプラットフォームを使用してコンパイルされました。次のコードの出力が異なるのはなぜですか?
-Osを使用してコンパイルすると、出力は次のようになります。0 42
c++ - 型エイリアシングと動的に割り当てられた配列
blitz++ 配列ライブラリーのコンパイラーによる自動ベクトル化を容易にしようとしています。このため、既に適切にベクトル化されている固定長ベクトルのチャンクにある配列データのビューを提示したいと思います。ただし、動的に割り当てられた配列と組み合わせて、型のエイリアシング規則が何を意味するのかわかりません。
これがアイデアです。現在、配列は次のもので構成されています
操作は、これらのデータをループすることによって行われます。私がやりたいのは、この配列の代替ビューを の配列として提示することですTinyVector<T_numtype, N>
。これは、式テンプレート機構を使用して演算が完全にベクトル化される固定長ベクトルです。T_numtype[L]
長さ L の配列は または のいずれかでなければならないという考え方TinyVector<T_numtype, N>[L/N]
です。タイプアラシングルールに違反することなくこれを達成する方法はありますか?
静的に割り当てられた配列の場合、次のようになります
私が考えることができる最も近いものは、定義することです
そしてそれを割り当てます
しかし、配列全体を T_numtype のフラットな配列としてアドレス指定する権利を放棄したようです。そのため、特定の要素にアクセスするには を行う必要がありdata_[i/N].data_[i%N]
、これははるかに複雑です。
では、 L が動的に決定されるサイズであるT_numtype data_[L]
andの和集合を合法的に作成する方法はありますか?TinyVector<T_numtype, N>[L/N]
(追加のアラインメントの問題があることは承知しています。つまり、N は TinyVector メンバーのアラインメントと同じ値でなければなりません。そうしないと、配列に穴ができてしまいます。)
c++ - gcc: __attribute((__may_alias__)) を適切に使用して、「derefence type-punned pointer」警告を回避する方法
オブジェクトを実際に使用する必要がある場合を除き、メンバーの「オブジェクト」のコンストラクターとデストラクタを呼び出す必要がないように、タイプパニングを使用するコードがあります。
正常に動作しますが、g++ 4.4.3 では、次の恐ろしいコンパイラ警告が表示されます。
私のコードは gcc の __attribute((__may_alias__)) を使用して gcc にエイリアシングの可能性を知らせようとしていますが、gcc は私が伝えようとしていることを理解していないようです。私は何か間違ったことをしていますか、それとも gcc 4.4.3 には __may_alias__ 属性に関する問題がありますか?
コンパイラの警告を再現するおもちゃのコードは次のとおりです。
c++ - 元のクラスへのポインタをキャストバックすると奇妙な動作になるのはなぜですか?
私のコードでは、データ メンバーとして格納し、必要に応じて元のポインターにvoid*
型キャストする必要があるとします。class
その信頼性をテストするために、テスト プログラム(linux ubuntu 4.4.1 g++ -04 -Wall)を作成しましたが、その動作を見てショックを受けました。
これは単なるテスト プログラムです。私の場合、実際には、ポインターを として保存void*
してから、実際のポインターにキャストすることが必須です (の助けを借りてtemplate
)。ですから、その部分は気にしないでください。上記のコードの出力は、
ただし、をに変更するvoid* p;
と、期待される動作A* p;
が得られます。なぜ ?
別の質問です。(A*&)
それ以外の場合は使用できませんoperator ++
。しかし、それは警告も出します。型がパニングされたポインターを逆参照すると、strict-aliasing rules が壊れます。warning を克服する適切な方法はありますか?
c++ - boost::optional が仮想関数を継承するクラスで失敗するのはなぜですか
boost::optional<> は単純なデータ型には完璧に機能しますが、インターフェイスを実装するクラスから継承するクラスに使用されるとすぐに、厳密なエイリアシングが有効になっていると失敗します。
例:
gcc バージョン 4.4.3 を使用して次のようにコンパイルすると、エラーが発生します。
この問題を解決する最善の方法は何ですか。厳密なエイリアス警告を有効にしたままにしておきたいと思います.boost バージョン 1.44 を使用しています。
アップデート:
ひどくなる!!次のコードを検討してください。
gcc バージョン 4.4.3 を使用して次のようにコンパイルすると、次のようにコンパイルされます。
「//コメント アウト」でマークされた行がコメント アウトされている場合、厳密なエイリアシング警告が表示されます。私はこれを少なくとも20回チェックしました。これは私が今まで見た中で最も奇妙なものの 1 つです。boost::optional が sth を初期化するように見えます。テンプレートパラメータから独立したり、sth で呼び出された場合にのみ boost::optional を理解するようになる gcc のように。最初に些細なこと。何か案は ?
c - C エイリアシングの制限 (共用体?) を克服する
次のようにコンパイルするサンプル ソース ファイル test.c があるとします。
$ gcc -03 -ウォール
test.c は次のようになります。
また、2 つの重複するポインターを渡すと、未定義の結果が得られるという制限を受け入れるとしましょう。
私はこのようなことを試しました(これらのマクロが各行の終わりにバックスラッシュでエスケープされた改行で適切にフォーマットされていると想像してください)
しかし、マクロ (a[0] < b[0]) で a を逆参照すると、gcc から「逆参照は厳格なエイリアス規則を破ります」というエラーが表示されます
ユニオンを使用して、メモリ内の 1 つの場所を 2 つの異なる方法で適切に参照する必要があると考えていたので、次のようなことを試しました。
ただし、厳密なエイリアシング規則に関して、コンパイラからまったく同じエラーが発生します。
だから:実際にメモリをコピーする以外に、厳密なエイリアスを壊さずにこれを行う方法はありますか?
( may_aliasはカウントされません。厳密なエイリアス規則をバイパスできるようにするだけです)
編集: memcmp を使用してこれを行います。エイリアシングのルールにとらわれてしまい、考えもしませんでした。
c++ - SSEデータ型とプリミティブ
ネット上のほとんどのチュートリアルまたはコードスニペットでは、次のように表示されます。
これは厳密なエイリアシングルールに違反していますか?確かにそうだと思いますが、チュートリアルの作成者はすべて、便宜上それを無視していません。__m128はfloat [4]を含むユニオンであるため、複雑な部分を誤解している可能性があります。