предупреждение о наказании - PullRequest
0 голосов
/ 21 марта 2012

Я хочу сделать что-то вроде этого:

#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

Есть ли способ использовать строгое предупреждение псевдонимов, но все же делать такие вещи?

Спасибо!

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)

Что вы все думаете об этом?

Ответы [ 2 ]

2 голосов
/ 21 марта 2012

Предупреждение связано с тем, что строка не может быть выровнена так же, как при объявлении целочисленной переменной. Таким образом, когда ЦПУ необходимо извлечь целочисленные значения, вы потенциально делаете его менее эффективным, чем могло бы быть (отсюда и предупреждение).

Вы можете начать с целых чисел, чтобы начать с:

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 голос
/ 21 марта 2012

Неважно, если вы в своем коде делаете назначения в этом случае. Ваш макрос будет генерировать инструкции загрузки / сохранения в любом случае, и они должны быть заказаны компилятором.

Один из способов решения строгих проблем с алиасами - использование союзов.

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;
}

Другое - использовать ключевое слово restrict. Используя это, вы гарантируете отсутствие псевдонимов, и компилятор может свободно упорядочивать манипуляции любым удобным для него способом, не рискуя получить нежелательные результаты. Но имейте в виду, что это своего рода контрактное программирование. Если вы ошиблись или кто-то изменил программу, это может привести к трудностям поиска ошибок.

...