Резюмируя: Да, это v alid в C, хотя он является незаконным в C++. Последний содержит эту записку, в которой объясняет разницу
Change: In C++, types may not be defined in return or parameter types. In C, these type definitions are allowed
Example:
void f(struct S { int a; } arg) {} // valid C, invalid C++
enum E { A, B, C } f() {} // valid C, invalid C++
- Обоснование: При сравнении типов в различных единицах компиляции, C++ опирается на имя эквивалентности, когда C зависит от структурной эквивалентности. Что касается типов параметров: поскольку тип, определенный в списке параметров, будет находиться в области функции, единственные юридические вызовы в C++ будут изнутри самой функции.
- Влияние на оригинальную функцию: Исключение семантически четко определенной функции.
- Сложность конвертации: Семантическая трансформация. Определения типов должны быть перемещены в область файла или в заголовочные файлы.
- Насколько широко используется: Редко. Этот стиль определений типов рассматривается как плохой стиль кодирования.
Структурная эквивалентность в C выполняется по понятию «совместимость типов». Это позволяет C обрабатывать многие типы, как если бы они были идентичны, хотя они теоретически различны - потому что они объявлены в двух разных единицах перевода. В C++ эта концепция не существует, поскольку типы имеют привязку и сопоставляются с одним и тем же объектом (например, чтобы функции-члены могли связываться друг с другом).
Обратите внимание, что приведенное выше объяснение основано на C89, которое не учитывало имя тега структуры при определении совместимости типов. В C89 draft, соответствующий текст гласит следующее:
Moreover, two structure, union, or enumeration types declared in separate translation units are compatible if they have the same number of members, the same member names, and compatible member types; for two structures, the members shall be in the same order;
В C99, проверка типа более строже: Если одна структуры имеет имя тега, другая декларация структуры должна иметь то же имя тега. Поэтому в вашем случае типа unnamed union, чтобы объявить функцию в другом TU, имеющем совместимый тип, вам понадобится unnamed union снова, если вы хотите иметь действительный код C99 (без неопределенного поведения) - вы не можете «обмануть», и использовать названный союз в одном TU и неназванный союз в другом TU. Мне кажется, что этот «трюк» действителен для C89. C99 TC3 6.2.7/1
:
Moreover, two structure, union, or enumerated types declared in separate translation units are compatible if their tags and members satisfy the following requirements: If one is declared with a tag, the other shall be declared with the same tag. If both are complete types, then the following additional requirements apply: there shall be a one-to-one correspondence between their members such that each pair of corresponding members are declared with compatible types, and such that if one member of a corresponding pair is declared with a name, the other member is declared with the same name. For two structures, corresponding members shall be declared in the same order.
, как вы хотите сделать это не работает. Вызов функции преобразует аргументы в тип параметров, как если бы они выполнялись при обычном назначении.
Итак, для этого вам придется иметь аргумент, совместимый с типом параметра. Для двух объединений, объявленных в , такой же блок перевода, это означает, что их тип должен быть равен - это единственный способ создать совместимый тип в пределах одной единицы перевода. Но это не сработает, потому что объявление неназванного объединения создает уникальный новый тип - никак не «ссылаться» на него с использованием другого объявления.
Итак, подведем итоги - вы должны указать название союза. Чтобы не создавать отдельную переменную для передачи необходимой базы аргумент, я бы объявить его вне функции, а также создавать функции, которые дают обратно в союз, вы можете пройти через
union base_type {
uint16_t b16;
uint32_t b32;
uint64_t b64;
};
int pcg_new_state(pcg_state *s,int arch,void *mem,int sz,
union base_type base,int self_running);
union base_type base_b16(uint16_t t)
{ union base_type b; b.b16 = t; return b; }
union base_type base_b32(uint32_t t)
{ union base_type b; b.b32 = t; return b; }
union base_type base_b64(uint64_t t)
{ union base_type b; b.b64 = t; return b; }
Теперь он может выглядеть следующим образом
pcg_new_state(...., base_b32(4211), ....);
Я не thinka союз подсчитываются как тип в этой ситуации, хотя. но это он: [earlz @ EarlzBeta- ~] $ gcc -v! Чтение спецификаций из /usr/lib/gcc-lib/amd64-unknown-openbsd4.5/3.3.5/specs! Конфигурируется с помощью:! Модель ничьи: single! gcc версия 3.3.5 (прополис)! (! Означает новую строку, так как комментарии не получают форматирование.) – Earlz
Почему бы вам просто не объявить союз как обычно, с именем? – 2009-08-02 22:14:01
Я полагаю, что мог бы, хотя я хочу, чтобы иметь возможность вызвать эту функцию без объявления новой переменной union и т. Д., Возможно ли это? – Earlz