2012-03-21 19 views
0

型punned警告

#define EQ4(a_,b_) (*(int*)(a_)==*(int*)(b_)) 

char *s1 = "food"; 
char *s2 = "fred"; 

return EQ4(s1,s2); 

が、gccが、この警告を生成している:警告:逆参照型punnedポインタは、厳密なエイリアシング規則を破るだろう。

ポインタ変数に逆参照されたポインタを割り当てていなかったので、厳密なエイリアシングの目的で逆参照としてカウントされていたことは考えませんでした。

私が試した:何の違いを行っていない

#define EQ4(a_,b_) (*(const int const *)(a_)==*(const int const*)(b_)) 

を。

のRedHat Linuxのバージョン2.6.32-220、gccのバージョン=

4.4.6は、厳密なエイリアシングの警告を使用する方法はありますが、それでもこのようなことはありますか?

ありがとうございます!これらは動作しません

EDIT

#define EQ4(a_,b_) (*(int*)(char*)(a_)==*(int*)(char*)(b_)) 
#define EQ4(a_,b_) (*(int*)(void*)(a_)==*(int*)(void*)(b_)) 
#define EQ4(a_,b_) (*(int* __attribute__((__may_alias__)))(a_)== \ 
        *(int* __attribute__((__may_alias__)))(b_)) 

これは動作します:

typedef union bork { char a[4], int n32 } __attribute__((__may_alias__)) TBork; 
#define EQ4(a_,b_) ((TBork*)(a_)->n32==(TBork*)(b_)->n32) 

あなたのすべては、このをどう思いますか?

+1

正しく整列してください。gccについてはわかりませんが、iccは正しく整列された 'char *'を認識し、警告を出しません。 – hroptatyr

+0

すべての回答ありがとうございます。アライメントのための警告は面白いです。 -march = 686でコンパイルしています。以前のバージョンのgccでは、私はmemcmpトリックをベンチマークしていました。現在のgccのバージョンは改善されているようです。それは小さな範囲ではmemcmpを下げます。私はおそらくこれらのトリックの多くを使用するのをやめることができますが、すべてではありませんので、私はまだすべての異なるアイデアに興味があります。 – johnnycrash

答えて

2

警告は、文字列が整数変数が宣言されたときと同じ方法で整列されることが保証されていないためです。したがって、CPUが整数値をフェッチする必要がある場合、潜在的に効率が低下します(したがって、警告)。

あなたがそもそもの整数で始めることができます:

int a; 
int b; 
char* as=(char*)(&a); 
char* bs=(char*)(&b); 
as[0]='f'; as[1]='o'; ... 
bs[0]='f'; bs[1]='r'; ... 
return EQ4(a, b); 

注:
1)あなたはそれがされるので、あなたがは、文字列の終端'\0'文字をコピーしないでくださいを確認する必要があります提供した例の場合は、a(またはb)の外部のメモリに触れてください(次の注意を参照してください)。
2)文字列が使用している特定のプラットフォームのintのサイズより大きくないことを確認する必要があります。そうでなければintに属していないメモリに(再び)触れます。

1

この場合、コード内で割り当てを行っても問題ありません。マクロはロード/ストア命令を生成しますが、これらはコンパイラによって順序付けされる必要があります。

厳密なエイリアシングの問題を処理する1つの方法は、共用体を使用することです。

inline bool my_equal(char *a, char *b) { 
    union { 
    char *cPointer; 
    int *iPointer; 
    } left_union = { .cPointer = a }, right_union = { .cPointer = b }; 

    return *left_union.iPointer == *right_union.iPointer; 
} 

もう1つはrestrictキーワードを使用することです。これを使用すると、エイリアシングが発生していないことが保証され、コンパイラは望ましくない結果を得るリスクを冒すことなく、操作が適切かどうかを自由に注文することができます。しかし、これは契約プログラミングの一種であることに留意してください。あなたが間違っている、または誰かがプログラムを変更すると、バグを見つけにくくなる可能性があります。

+0

"_Anotherはrestrictキーワードを使用します._" – curiousguy