Ответ 1
Он терпит неудачу, потому что {3, 4}
, хотя он действительный инициализатор, не является выражением (по крайней мере, он не находится в C, см. ниже, чтобы узнать больше о С++).
Каждое выражение в C имеет тип, который можно определить, исследуя само выражение. {3, 4}
потенциально может иметь тип struct T
или int[2]
(тип массива) или любое из множества других типов.
C99 добавила новую функцию, называемую составными литералами, которые используют аналогичный синтаксис для инициализаторов, но позволяю вам указывать тип, создавая выражение:
b = (struct T){3, 4};
Обратите внимание, что (struct T)
не является оператором трансляции; это часть синтаксиса составного литерала.
Дополнительную информацию о составных литералах см. в разделе 6.5.2.5 проекта проекта стандарта C11.
Компонентные литералы были введены в 1999 году стандартом ISO C (C99). Если ваш компилятор не поддерживает C99 или лучше (* cough * Microsoft * cough *), вы не сможете их использовать.
Если вы используете С++ (который, не забывайте, это другой язык), он не поддерживает сложные литералы, но может быть и альтернатива. Как отмечает Potatoswatter в комментарии, это:
b = T{3, 4};
действителен в С++ 11 (но не в более ранних версиях языка С++). Это описано в разделе 5.2.3 [expr.type.conf] стандарта С++.
В этом отношении:
b = {3, 4};
также является синтаксисом С++ 11. Эта форма может использоваться в ряде определенных контекстов, включая правую часть задания. Это описано в разделе 8.5.4 [dcl.init.list] стандарта С++.
Один недавний проект стандарта С++ - N3485.
(g++ поддерживает сложные литералы C99 в С++ в качестве расширения.)
И если вы застряли с компилятором pre-C99, вы всегда можете написать свою собственную функцию инициализации, например:
struct T init_T(int x, int y) {
struct T result;
result.x = x;
result.y = y;
return result;
}
/* ... */
struct T obj;
/* ... */
obj = init_T(3, 4);
Это раздражающее количество дополнительной работы (именно поэтому C99 добавил сложные литералы), но он выполняет эту работу. С другой стороны, в большинстве случаев вам, вероятно, лучше использовать инициализацию:
struct T obj;
/* ... */
{
struct T tmp = { 3, 4 };
obj = tmp;
}
Что лучше, вероятно, зависит от того, как структурирована ваша программа.