У меня есть код, который выглядит примерно так, где addr является sockaddr*:
struct sockaddr_in *sin = (struct sockaddr_in *) addr;
const char *IP=inet_ntoa(sin -> sin_addr);
Я полагаю, что это - очень типичный код для использования сокетов Беркли.
Однако, когда я компилирую это, я получаю соблюдающее предупреждение:
dereferencing pointer 'sin' does break strict anti-aliasing rules
Ища онлайн, я нахожу некоторое обсуждение того, что способ, которым я делаю вещи, довольно типичен, но это предупреждение компилятора также довольно реально и не хорошая вещь.
Что надлежащий путь состоит в том, чтобы восстановить этот код, чтобы зафиксировать предупреждение и не просто заставить его замолчать?
Да, это известная проблема с gcc и сокетами. Проблема в основном в том, что способ разработки этого ip [46] несовместим с предположениями, которые, по мнению специалистов GCC, они могут сделать о наложении имен указателей.
Обычно я избегаю этого, сначала беря указатель на struct
struct in_addr* act = &(sin->sin_addr);
, а затем используя * act
.
В зависимости от того, как вы использовали struct sockaddr
, я думаю, что либо ваш код не работает, либо gcc. struct sockaddr
и struct sockaddr_in
имеют общий начальный элемент ( sa_family
/ sin_family
), поэтому он не нарушает правила псевдонима, если вы получили доступ только этот элемент через оба указателя; это разрешено C99. Более того, struct sockaddr
не имеет других элементов, к которым вам разрешен доступ. Это в значительной степени непрозрачный тип для примитивного полиморфизма адресов сокетов. Если вы копались во внутренностях конкретной реализации в struct sockaddr
или, что еще хуже, если вы объявили объект struct sockaddr
, а не просто указатель или выполнили копирование между такими объектами, ваш код не работает. Если вы этого не сделали, и gcc выдает предупреждение о том, что вы нарушили правила псевдонима, то генерация предупреждения gcc не работает. Я, конечно, не удивлюсь, если это будет последнее.
Если ваш заголовочный файл и ваш компилятор являются частью одной и той же реализации C или C++, пожалуйтесь своему поставщику и попросите его поместить подходящую #pragma в его заголовочный файл, чтобы заставить замолчать его компилятор. Как реализатору, им разрешено играть в подобные игры, пока они предоставляют соответствующую реализацию.
Если ваш заголовочный файл и ваш компилятор пришли из двух разных реализаций C или C++, вам повезло, что все работает так хорошо, как работает, и вам придется решать проблему самостоятельно.