В gcc-strict-aliasing-and-casting-through-a-union Я спросил, не сталкивался ли кто-нибудь с проблемами с наложением союзов через указатели. Пока что, похоже, ответ Нет .
Этот вопрос является более широким: у вас есть какие-либо страшные истории о gcc и строгом псевдониме?
Справочная информация: Цитата из Ответ AndreyT в c99-strict-aliasing-rules-in-c-gcc :
"Строгие правила псевдонимов коренятся в частях стандарта, которые присутствовали в C и C ++ с начала [стандартизированных] времен. Пункт, который запрещает доступ к объекту одного типа через lvalue другого типа, присутствует в C89 / 90 (6.3), а также в C ++ 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.
Некоторые другие менее релевантные ссылки:
Итак, повторюсь, у вас есть собственная история ужасов? Проблемы , а не , обозначенные -Wstrict-aliasing
, конечно, будут предпочтительнее. И другие компиляторы Си также приветствуются.
Добавлено 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's 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 инвертируется (что означает, что фиктивное len записывается в поток).
Скомпилированный код, используя gcc 4.3.4 на CYGWIN с -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;
Я спросил SO, все ли в порядке в gcc-строго-псевдонимах-и-каст-через-объединение , но пока никто не согласен.