Ответ 1
Оба используют совершенно разные механизмы, один из которых является С++ 11-специфичным, другой из которых является C99-специфичным.
Первый бит,
struct A get() {
return {0};
}
зависит от [stmt.return] (6.6.3 (2)) в С++ 11, в котором говорится, что
(...) Оператор return с бин-init-list инициализирует объект или ссылку, возвращаемую функцией, путем инициализации списка-списка из указанного списка инициализаторов. [Пример:
std::pair<std::string,int> f(const char *p, int x) { return {p,x}; }
- конец примера]
Этот фрагмент не существует в C (и С++ до С++ 11), поэтому компилятор C не может его обработать.
С другой стороны,
struct A get() {
return (struct A){0};
}
использует функцию C99, называемую "составные литералы", которая не существует в С++ (хотя некоторые компиляторы С++, особенно gcc, предоставляют ее как расширение языка, gcc предупреждает об этом с помощью -pedantic). Семантика подробно описана в разделе 6.5.2.5 стандарта C99; денежная цитата
4 Постфиксное выражение, состоящее из имени типа в скобках, за которым следует список инициализаторов, заключенных в скобки, является сложным литералом. Он предоставляет неназванный объект, значение которого задается в списке инициализаторов. (сноска 80)
80) Обратите внимание, что это отличается от литого выражения. Например, cast задает преобразование только для скалярных типов или
void
, а результат литого выражения не является lvalue.
Таким образом, в этом случае (struct A){0}
является неназванным объектом, который копируется в возвращаемое значение и возвращается. (обратите внимание, что современные компиляторы вернутся к этой копии, поэтому вам не нужно опасаться накладных расходов во время выполнения)
И у вас есть это, главы и стихи. Почему эти особенности существуют так, как они делают на их соответствующих языках, могут оказаться увлекательной дискуссией, но я боюсь, что любому, кто не соответствует стандартам комитетов по стандартизации, не будет дать авторитетный ответ на этот вопрос. Обе функции были введены после разделения C и С++, и они не развиты бок о бок (и не имеет смысла это делать). Дивергенция неизбежна даже в мелочах.