[解決済み] 型依存のポインタの再参照がストリクトエイリアスを破壊する問題の修正
質問
GCCを使用して特定のプログラムをコンパイルする際、2つの警告を修正しようとしています。 警告は次のとおりです。
警告: 型打ちされたポインタの再参照は ストリクトエイリアスのルール [-Wstrict-aliasing] に従います。
で、犯人はこの2つです。
unsigned int received_size = ntohl (*((unsigned int*)dcc->incoming_buf));
そして
*((unsigned int*)dcc->outgoing_buf) = htonl (dcc->file_confirm_offset);
着信バッファー と アウトゴーイング_バフ は以下のように定義されています。
char incoming_buf[LIBIRC_DCC_BUFFER_SIZE];
char outgoing_buf[LIBIRC_DCC_BUFFER_SIZE];
これは、私が調べてきたその警告の他の例とは微妙に違うようです。 ストリクト・エイリアシング・チェックを無効にするのではなく、問題を修正することを希望します。
ユニオンを使うという提案はたくさんありますが、このケースに適したユニオンは何でしょうか?
どのように解決するのですか?
まず最初に、エイリアシング違反の警告が出る原因を調べてみましょう。
エイリアシングルール
は、単にオブジェクト自身の型、符号付き/符号なしバリアント型、または文字型(
char
,
signed char
,
unsigned char
).
C言語では、エイリアシングのルールに違反すると未定義の動作が呼び出されます ( ということで、don't! ).
あなたのプログラムのこの行で。
unsigned int received_size = ntohl (*((unsigned int*)dcc->incoming_buf));
の要素がありますが
incoming_buf
配列の型は
char
としてアクセスすることになります。
unsigned int
. 確かに、式中のデリファレンス演算子の結果は
*((unsigned int*)dcc->incoming_buf)
は
unsigned int
型になります。
の要素にアクセスする権利しかないので、これはエイリアスルールに違反しています。
incoming_buf
を通して配列することができます (上記のルールの概要を参照してください!)
char
,
signed char
または
unsigned char
.
2番目の原因でもまったく同じエイリアシングの問題があることに注意してください。
*((unsigned int*)dcc->outgoing_buf) = htonl (dcc->file_confirm_offset);
にアクセスします。
char
の要素で構成されています。
outgoing_buf
を通して
unsigned int
ということで、エイリアス違反になります。
解決策案
この問題を解決するには、配列の要素をアクセスしたい型に直接定義するようにすればよいでしょう。
unsigned int incoming_buf[LIBIRC_DCC_BUFFER_SIZE / sizeof (unsigned int)];
unsigned int outgoing_buf[LIBIRC_DCC_BUFFER_SIZE / sizeof (unsigned int)];
(ちなみに
unsigned int
は実装で定義されているので
uint32_t
を想定している場合は
unsigned int
は32ビット)。
この方法では
unsigned int
を使用して要素にアクセスすることで、 エイリアスルールに違反することなく配列にオブジェクトを追加できます。
char
を、このようにします。
*((char *) outgoing_buf) = expr_of_type_char;
または
char_lvalue = *((char *) incoming_buf);
EDITです。
特に、なぜプログラムがコンパイラからエイリアシングの警告を受けるのかを説明しています。
関連
-
[解決済み】エラー:cの入力の最後に期待される宣言またはステートメント
-
[解決済み】Valgrind - strcpyのサイズ1の無効な書き込み
-
[解決済み】単項演算子「*」の型が無効(「int」がある)C言語でのエラー
-
[解決済み】ポインタと整数の比較で警告が出る
-
[解決済み】初期化がキャストなしで整数からポインタを作成 - C言語
-
[解決済み】Cygwin - Makefile-error: ターゲット `main.o' のレシピに失敗しました。
-
[解決済み] [Solved] なぜこのようなエラーが発生するのでしょうか。「データ定義に型またはストレージクラスがない」?
-
[解決済み] struct has no member named
-
[解決済み] エラー:整数が期待されるところで集約値が使用された
-
[解決済み】インクリメントオペランドとして lvalue が必要です。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C言語で「関数の型が競合しています」と表示される、なぜ?
-
[解決済み】"Expected expression before ' { ' token"(トークンの前に期待される式)。
-
[解決済み】C 未知の型名「my_structure」。
-
[解決済み】MB/sとMiB/sを計算する方法は?
-
[解決済み】int型配列へのポインタのスカラ・イニシャライザの過剰要素
-
[解決済み】未定義参照 makefile が間違っているのかも?
-
[解決済み] エラー: `itoa` はこのスコープで宣言されていません。
-
[解決済み] Cプログラムで「配列の添え字が整数でない」。
-
[解決済み】Linuxソケットのwrite()でBad File Descriptorが発生するC
-
[解決済み】c - 警告:関数 'printf'の暗黙の宣言