Hmmm, станд.:: строка не является тем же как символом константы *. Я обычно допускаю ошибку на стороне использования станд.:: представьте в виде строки, потому что это - класс, который имеет много дополнительных возможностей, которые делают намного легче использовать.
, Если производительность является главной и Вы используете символ константы * для эффективности, идете тем путем.
Подводя итог: Да, это допустимо в C, хотя является незаконным в C ++. Последний содержит это примечание, объясняющее разницу
Изменение: В C ++ типы не могут быть определены в типах возвращаемых данных или в типах параметров. В C эти определения типов разрешены
Пример:
void f( struct S { int a; } arg ) {} // valid C, invalid C++
enum E { A, B, C } f() {} // valid C, invalid C++
Структурная эквивалентность в C достигается за счет концепции «совместимости типов». Это позволяет C рассматривать многие типы, как если бы они были идентичными, даже если они теоретически различны - потому что они объявлены в двух разных единицах трансляции. В C ++ такой концепции не существует, поскольку типы связаны и сопоставляются с одним и тем же объектом (т. e, чтобы позволить функциям-членам связываться друг с другом).
Обратите внимание, что процитированное выше объяснение основано на C89, который не учитывал имя тега структуры при определении совместимости типов. В черновике C89 соответствующий текст читается следующим образом:
Кроме того, два типа структуры, объединения или перечисления, объявленные в отдельных единицах перевода, совместимы, если они имеют одинаковое количество членов, одинаковые имена членов и совместимые типы членов; для двух структур члены должны быть в одинаковом порядке;
В C99 проверка типов более строгая: если одна структура имеет имя тега, объявление другой структуры должно иметь такое же имя тега. Итак, в случае вашего безымянного типа объединения, чтобы объявить функцию в другом TU, имеющем совместимый тип, вам снова понадобится безымянное объединение, если вы хотите иметь действительный код C99 (без неопределенного поведения) - вы не можете «обмануть» и использовать именованное объединение в одном TU и безымянное объединение в другом TU. Мне кажется, что этот "трюк" применим и для C89. C99 TC3 6.2.7 / 1
:
Более того, два типа структуры, объединения или перечисления, объявленные в отдельных единицах перевода, совместимы, если их теги и члены удовлетворяют следующим требованиям: Если один объявлен с тег, другой должен быть объявлен с таким же тегом. Если оба являются полными типами, применяются следующие дополнительные требования: между их членами должно быть взаимно однозначное соответствие, так что каждая пара соответствующих членов объявляется с совместимыми типами, и так, что если один член соответствующей пары объявляется с именем, другой член объявляется с тем же именем. Для двух структур члены-корреспонденты должны быть объявлены в том же порядке.
То, как вы хотите это сделать, не работает. Вызов функции преобразует аргументы в тип параметров, как если бы при обычном назначении.
Итак, чтобы это работало, у вас должен быть аргумент, совместимый с типом параметра. Для двух объединений, объявленных в одной и той же единице трансляции, это означает, что их типы должны быть одинаковыми - это единственный способ найти совместимый тип в одной и той же единице трансляции. Но это не может сработать, потому что объявление безымянного объединения создает уникальный новый тип - нет возможности «вернуться» к нему с помощью другого объявления.
Итак, Подводя итог - вы должны дать типу объединения имя. Чтобы не создавать отдельную переменную для передачи необходимого базового аргумента, я бы объявил ее вне функции и создал функции, возвращающие объединение, которое вы можете передать
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), ....);
Как насчет этого:
typedef struct _base
{
union
{
uint16_t b16;
uint32_t b32;
uint64_t b64;
};
}Base;
int func(Base b)
{
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
Base b;
b.b16 = 0xFFFF;
func(b);
return 0;
}
Вы можете заставить это скомпилировать в GCC, указав объединение с именем в функции, но вы не не могу использовать его из-за объема определения, как предупреждает GCC:
test_union.c:14: warning: ‘union X’ declared inside parameter list
test_union.c:14: warning: its scope is only this definition or declaration, which is probably not what you want
Код:
int pcg_new_state(pcg_state *s,int arch,void *mem,int sz,
union X{
uint16_t b16;
uint32_t b32;
uint64_t b64;
}base ,int self_running);
Размер союза в любом случае будет размером самого большого члена - так что вы ничего не получите. С таким же успехом вы можете просто сделать параметр uint64_t, поскольку преобразования из больших в меньшие беззнаковые типы четко определены и обычно дешевы в реализации. (Например, присвоение uint64_t uint16_t может быть выполнено просто путем взятия младших 16 битов более широкого типа.)
EDIT : Например
int pcg_new_state(pcg_state *s,int arch,void *mem,int sz, uint64_t param_base ,int self_running)
{
/* Implementation for 16 bit arch */
uint16_t base = param_base;
/* ... more code ... */
}
Я быстро просмотрел стандарт (Edit: C ++) и не увидел ничего запрещающего ни в 8.3.5 - Функции [dcl.fct], ни в 9.5 - Союзы [class. союз]. Как полуобразованное предположение, я бы сказал, что законно принимать профсоюз, но не объявлять один подобный встроенный. GCC дает:
ошибка: типы не могут быть определены в типах параметров.
Так что вам придется определить тип заранее.
Даже если это законно, однако, это не значит, что это хорошо идея. Просто взглянув на него, я бы предположил, что, возможно, перегрузка может предоставить лучшее решение. Но, конечно, вы знаете свой код лучше всех ... просто подумав, что вам может понадобиться поискать более простое и идиоматическое решение.