1

私はこのようなことをしたい:

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

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

return EQ4(s1,s2);

しかし、gcc は次の警告を出しています:

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

私は試した:

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

違いはありませんでした。

Redhat Linux バージョン 2.6.32-220、gcc バージョン = 4.4.6

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

ありがとう!

編集

これらは機能しません:

#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)

皆さんはこれについてどう思いますか?

4

2 に答える 2

2

警告は、整数変数が宣言されたときと同じように文字列が整列されることが保証されていないためです。したがって、CPUが整数値をフェッチする必要がある場合、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)提供した例の場合、文字列の終了文字が(または)の外部のメモリに接触するため、文字列の終了文字をコピーしないようにする必要があります(次の注を参照)。 2)文字列が使用している特定のプラットフォームのintのサイズより大きくないことを確認する必要があります。そうでない場合、intに属していないメモリに(再び)触れています。'\0'ab

于 2012-03-21T16:41:54.833 に答える
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キーワードを使用することです。これを使用すると、エイリアシングが発生せず、コンパイラーが不要な結果を得るリスクを冒すことなく、適切と思われる方法で操作を自由に注文できることが保証されます。ただし、これは一種の契約プログラミングであることに注意してください。あなたが間違っているか、誰かがプログラムを変更した場合、これはバグを見つけるのが難しい結果になるかもしれません。

于 2012-03-21T17:06:29.613 に答える