kika: (Default)
[personal profile] kika
[livejournal.com profile] pzz написал код, который приводит в изумление компилятор MS VS 2005 в режиме С, но отлично потребляется им же в режиме C++ и gcc в любом режиме.
Выжимка этого кода:
typedef union { char a; } u;
typedef struct{ u a1; } s;
void foo(u *up) { s s1 = { *up }; }

Приводит к
error C2440: 'initializing' : cannot convert from 'u' to 'char'

Кротофф, скажи что я лох?

Re: Ты лох

Date: 2007-01-30 07:42 pm (UTC)
From: [identity profile] krotoff.livejournal.com
А что за ворнинг ?

Re: Ты лох

Date: 2007-01-30 07:45 pm (UTC)
From: [identity profile] kika.livejournal.com
warning C4047: 'initializing' : 'char' differs in levels of indirection from 'char *'

Date: 2007-01-30 07:50 pm (UTC)
From: [identity profile] krotoff.livejournal.com
Ой, не увидел, что 'a' там уже массив.

Date: 2007-01-30 07:59 pm (UTC)
From: [identity profile] kika.livejournal.com
Anyway, насколько я понимаю в этом месте С и С++ отличаться не должны. А отличаются.

Date: 2007-01-30 09:14 pm (UTC)
From: [identity profile] krotoff.livejournal.com
Вопрос весьма талмудический, я такие люблю ;-)

Сегодня уже ничего не соображаю, завтра посмотрю нормативные акты подробнее (прошли те времена, когда все эти завихи помнил хорошо).

Date: 2007-01-31 09:55 am (UTC)
From: [identity profile] krotoff.livejournal.com
По прошествии:
Разбираем:

void foo(u *up) {
s s1 = { *up };
s s2 = { up->a };
u s3 = *up;
u s4 = up->a;
#ifdef __cplusplus
u s5(*up);
u s6(up->a);
#endif
}

По правилам с++ ошибкочными будут инициализации s4 и s6.
s1 пройдет по правилам агрегатной инициализации по той причине, что у u есть конструктор копирования. А по правилам 8.5.1 p12 это правило применяется первым, до попытки непосредственной почленной инициализации агрегата.

По правилам c при агрегатной инициализации union сам по-себе объект union не инициализируется (у него нет конструкторов, в том числе копикрота), и правила применяются рекурсивно к его первому члену. В данном случае к a, и получаем, что массив можно инициализировать только почленно.

The initializer for a structure or union object that has automatic storage duration shall be either an initializer list as described below, or a single expression that has compatible structure or union type. In the latter case, the initial value of the object, including unnamed members, is that of the expression.

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

Date: 2007-01-31 01:41 pm (UTC)
From: [identity profile] kika.livejournal.com
В данном случае к a, и получаем, что массив можно инициализировать только почленно.

1. Почему тогда работает s3 ?
2. Ты получишь ту же самую ошибку, если a не будет массивом, но тогда есть workaround в виде s4.

Date: 2007-01-31 01:46 pm (UTC)
From: [identity profile] krotoff.livejournal.com
1. Потому что инициализировать как не-агрегатом значением совместимого типа можно (цитата выше, но по ней не виден контекст). Правила для агрегатов и прямой инициализации в С отличаются более существенно, чем в с++.

Date: 2007-01-31 01:50 pm (UTC)
From: [identity profile] kika.livejournal.com
Ачуметь вообще. Странно что это в С не починили до сих пор.
Да, спасибо, похоже что я таки лох, но в таком месте это не стыдно :-)

Profile

kika: (Default)
kika

January 2017

S M T W T F S
1234567
89 1011121314
151617181920 21
22232425262728
293031    

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 16th, 2026 11:09 am
Powered by Dreamwidth Studios