2

gcc次のコードがエラーなしで正常に動作する理由がわかりません( -fstrict-aliasing -Wstrict-aliasing=1)。

#include <stdio.h>

int 
main(void) 
{
    char  n = 42;
    char *p = &n;
    int  *q = (int *)p;

    *q = 10;

    printf("%d|%d\n", *p, *q);

    return 0;
}

厳密なエイリアシング ルールに従うと、次のようになります。

n1570、§ 6.5 式

オブジェクトは、次の型のいずれかを持つ左辺値式によってのみアクセスされる格納された値を持つものとします。

— オブジェクトの有効な型と互換性のある型、

— オブジェクトの有効な型と互換性のある型の修飾されたバージョン

- オブジェクトの有効な型に対応する符号付きまたは符号なしの型である型、

- オブジェクトの有効な型の修飾されたバージョンに対応する符号付きまたは符号なしの型である型、

— 前述のタイプのいずれかをメンバーに含む集約型または共用体型 (再帰的に、サブ集約または含まれる共用体のメンバーを含む)、または

— 文字タイプ。

ただし、修飾されたバージョン、対応する符号付きまたは符号なしの型、文字型のいずれか*qと互換性のある型はありません。*p

では、なぜ許可されているのでしょうか。

4

1 に答える 1

3

それは許可されていません。投稿した標準の一部は、オブジェクトのエイリアスに許可されているタイプを示しています。

コードがコンパイルされたという事実は、それが正しいことを意味しません。プログラムが未定義の動作を示すコードに 3 つの問題があります。

まず、char ポインターを int ポインターに割り当てたことです。標準はそれらの配置と表現を強制しないため、結果のポインターは有効ではありません。

int  *q = (int *)p;

char n次に、オブジェクトを整数として解釈し、厳密なエイリアシングに違反しました(質問の標準からの引用に注意してください)。

*q;

最後にint、 を char オブジェクト ( char n) のメモリに書き込みました。これにより、 an のサイズintが常に a のサイズよりも大きいため、オーバーフローが発生しcharます。

*q = 10;
于 2014-12-23T19:24:42.460 に答える