2017-06-29 8 views
0

ポインタのキャスティングは実際に厳密なエイリアシングを解除しますか?次のコードで

#include <stdio.h>    

int main(void) 
{ 
    int n = 74; 
    int * pn = &n; 

    short * sp; 

    //sp = (short *)&n; // <-- bad 
    sp = (short *)pn; // <-- fine 

    *sp = 4; 
    printf("%d\n", *sp); 

    return 0; 
} 

厳格なエイリアシング規則が壊れて取得するのですか?私が理解する限り、intへの短い点を指すポインタがあるので、それはします。 (test.cの中にあるコードを仮定して)でコンパイルされた場合でも、コンパイラはラインが悪いがコメント解除されているマークされ、もう1つはコメントしている微細なマークされている場合

gcc test.c -o test.exe -Wall -std=c99 -Wstrict-aliasing=2 -O3 

しかし、それは文句を言わなくても文句はありません。

誰かが説明することができますこのケースは本当にルールを破るか?もしそうなら、それはなぜコンパイラによって検出されないのですか?もしそうでなければ、標準によればそれはすべきではないのですか?

+2

コンパイラの警告は、明らかに見えるものであっても、すべてをキャッチしません。 – user2357112

+0

"コンパイラは文句を言っていません" - ネットを使わずにコーディングしてCを歓迎します。 – chux

+0

言語を選択します。 CとC++はここでは若干異なる規則を持っています。 – Lundin

答えて

2

厳密なエイリアシングに違反するのは、それ自体がキャストではありません。違反した後続の無効な左辺値のアクセス(メモリの再解釈)です。

厳密なエイリアシング違反は実際には実行時違反です。動的のlvaluesとしてアクセスされるオブジェクトのタイプによって定義されます。このため、コンパイル時に厳密なエイリアス違反を検出することは必ずしも可能ではありません。

は、次のコードは、それはあなたの元のコードと同じキャスト(2)が含まれていても、厳密なエイリアシング規則に違反しない

short n = 0; 
int *pn = (int *) &n;  // 1 
short *sp = (short *) pn; // 2 
*sp = 4; 

このコードスニペット考えてみましょう。ポインタpnint *と宣言されていますが、実行時には実際にはタイプshortのオブジェクトを指しています。したがって、short *へのキャストおよびその後のpointeeへの割り当ては完全に有効です。

このような場合、コンパイラは明らかにキャストのチェーンの最初のキャストをキャッチしようとしているように見えます。キャストのチェーンの最初のキャストをキャッチするように見えます。潜在的な厳密なエイリアシングの違反 - 私の例ではキャスト1。キャスト2は(私の例のように)偽陽性を生成する可能性がかなり高く、コンパイラは警告しません。

+0

'コンパイラは、潜在的な厳密なエイリアシングの違反と思われるキャストのチェーン内の最初のキャストをキャッチしようとしています。私はこの主張を支持するための文書を見ていました。あなたはリンクを含めることができますか? – sjsam

2

コンパイラがコンパイル時に違反をキャッチするのは、次のように別の型に逆参照することで新しい値を割り当てない限り困難です。以下のようにコードを変更すると、予期していた警告が表示されます。

int main(void) 
{ 
    int n = 74; 
    //int * pn = &n; 

    //short * sp; 

    //sp = (short *)&n; // <-- bad 
    //sp = (short *)pn; // <-- fine 

    *((short*)&n) = 4; 
    printf("%d\n", n); 

    return 0; 
} 

この質問はまったく同じ問題を示し、さらに詳細を示します。 GCC: accuracy of strict aliasing warnings

ANTで他の答えは、この文で始まっ: は「それはそれは、その後の不正な左辺値へのアクセス、それに違反する(メモリ再解釈)で、厳格なエイリアシングに違反キャスティング自体ではありません。」 .... それは正しいです。私の例では、ルールに違反するlvalueアクセスを試みるので、警告が表示されます。

関連する問題