В gcc-strict-aliasing-and-casting-through-a-union Я спросил, кто-то сталкивался с проблемами с профсоюзом, набирая указатели. Пока что ответ кажется No.
Этот вопрос шире: есть ли у вас какие-то ужасные истории о gcc и строгом псевдониме?
Справочная информация: цитата из Ответ AndreyT в c99-strict-aliasing-rules-in-c-gcc:
"Строгие правила псевдонимов основаны на части стандарта, которые присутствовали на C и С++ с начала [стандартизованных] раз. Предложение, запрещающее доступ к объекту одного типа через lvalue другого типа, присутствует в C89/90 (6.3), а также в С++ 98 (3.10/15).... То, что не все компиляторы хотели (или посмели) обеспечить его выполнение или полагаться на него".
Ну, gcc теперь смеет это делать, с его переключателем -fstrict-aliasing
. И это вызвало некоторые проблемы. См., Например, отличную статью http://davmac.wordpress.com/2009/10/ об ошибке Mysql, а также отличное обсуждение в http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html.
Некоторые другие менее релевантные ссылки:
- performance-impact-of-fno-strict-aliasing
- strict-aliasing
- when-is-char-safe-for-strict-pointer-aliasing
- how-to-detect-strict-aliasing-at-compile-time
Итак, чтобы повторить, есть ли у вас ужасная история? Конечно, проблемы не, обозначенные -Wstrict-aliasing
, были бы предпочтительнее. И другие компиляторы C также приветствуются.
Добавлено 2 июня. Первая ссылка в ответе Майкла Барра, которая действительно квалифицируется как история ужасов, возможно, немного устарела (с 2003 года). Я сделал быстрый тест, но проблема, очевидно, исчезла.
Источник:
#include <string.h>
struct iw_event { /* dummy! */
int len;
};
char *iwe_stream_add_event(
char *stream, /* Stream of events */
char *ends, /* End of stream */
struct iw_event *iwe, /* Payload */
int event_len) /* Real size of payload */
{
/* Check if it possible */
if ((stream + event_len) < ends) {
iwe->len = event_len;
memcpy(stream, (char *) iwe, event_len);
stream += event_len;
}
return stream;
}
Конкретная жалоба:
Некоторые пользователи жаловались, что, когда код [выше] скомпилирован без -fno-strict-aliasing, порядок записи и memcpy инвертируется (что означает, что фиктивная линя копируется в поток).
Скомпилированный код, используя gcc 4.3.4 на CYGWIN wih-O3 (пожалуйста, поправьте меня, если я ошибаюсь - мой ассемблер немного ржавый!):
_iwe_stream_add_event:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
movl 8(%ebp), %eax # stream --> %eax
movl 20(%ebp), %edx # event_len --> %edx
leal (%eax,%edx), %ebx # sum --> %ebx
cmpl 12(%ebp), %ebx # compare sum with ends
jae L2
movl 16(%ebp), %ecx # iwe --> %ecx
movl %edx, (%ecx) # event_len --> iwe->len (!!)
movl %edx, 8(%esp) # event_len --> stack
movl %ecx, 4(%esp) # iwe --> stack
movl %eax, (%esp) # stream --> stack
call _memcpy
movl %ebx, %eax # sum --> retval
L2:
addl $20, %esp
popl %ebx
leave
ret
И для второй ссылки в Майкле ответьте,
*(unsigned short *)&a = 4;
gcc будет обычно (всегда?) давать предупреждение. Но я считаю, что правильное решение для этого (для gcc) заключается в использовании:
#define CAST(type, x) (((union {typeof(x) src; type dst;}*)&(x))->dst)
// ...
CAST(unsigned short, a) = 4;
Я спросил, правильно ли это в gcc-strict-aliasing-and-casting-through-a-union, но пока никто не согласен.