2015-07-23 2 views
22

Во время чтения статьи, я наткнулся на следующую функцию:Одд синтаксис в C++: возвращение {.name = значение, ...}

SolidColor::SolidColor(unsigned width, Pixel color) 
    : _width(width), 
    _color(color) {} 

__attribute__((section(".ramcode"))) 
Rasterizer::RasterInfo SolidColor::rasterize(unsigned, Pixel *target) { 
    *target = _color; 
    return { 
    .offset = 0, 
    .length = 1, 
    .stretch_cycles = (_width - 1) * 4, 
    .repeat_lines = 1000, 
    }; 
} 

Что автор делает с обратным утверждением? Раньше я не видел ничего подобного, и я не знаю, как его искать ... Действительно ли это справедливо для простого С?

Edit: link to the original article

+5

Действителен в C, нестандартном расширении некоторых компиляторов для C++ (как и в C++ 11, эта функциональность отсутствует в стандарте C++.) –

+2

См. [Стандарт C] (http: //www.open- std.org/jtc1/sc22/wg14/www/docs/n1570.pdf), раздел _6.5.2.5 Компонентные литералы_, пункт 10 (относительно назначенных инициализаторов). – Michael

+1

Я уверен, что это верно для простых C и _not_ для C++. – davmac

ответ

21

Это недопустимо C++.

Это (вид), используя пару функций из C, известных как «сложные литералы» и «назначенные инициализаторы», которые несколько компиляторов C++ поддерживают как расширение. «Своего рода» исходит из того факта, что быть законным C соединение буквальным, он должен иметь синтаксис, который выглядит как литой, так что вам придется что-то вроде:

return (RasterInfo) { 
    .offset = 0, 
    .length = 1, 
    .stretch_cycles = (_width - 1) * 4, 
    .repeat_lines = 1000, 
    }; 

Независимо от разницы в синтаксисе, однако, это в основном создает временный-структуру с членами инициализируется, как указано в блоке, так что это примерно эквивалентно:

// A possible definition of RasterInfo 
// (but the real one might have more members or different order). 
struct RasterInfo { 
    int offset; 
    int length; 
    int stretch_cycles; 
    int repeat_lines; 
}; 

RasterInfo rasterize(unsigned, Pixel *target) { 
    *target = color; 
    RasterInfo r { 0, 1, (_width-1)*4, 1000}; 
    return r; 
} 

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

+0

Просто 'return {0, 1, (_width-1) * 4, 1000};' в C++ 11 работает, нет необходимости в 'r'. Что придает синтаксис C++ ближе к синтаксису C99 и делает слияние двух синтаксисов, используемых выше. – Yakk

9

Это C99 compound literal. Эта особенность специфична для C99, но gcc и clang также выбирают реализацию на C++ (как extension).

6,26 Составные литералы

ISO С99 поддерживает составные литералов. Комбинированный литерал выглядит как листинг , содержащий инициализатор. Его значение представляет собой объект типа , указанный в литье, содержащий элементы, указанные в инициализаторе ; это значение lvalue. В качестве расширения GCC поддерживает составные литералы в режиме C90 и в C++, хотя семантика несколько отличается от на C++.

+1

Ум, что? "... похоже на листинг, содержащий инициализатор. что соответствует вопросу? -1. – Barry

+0

То есть _not_ complex initializer_! Это потребует тип в скобках перед блоком. И исходный код - C++, даже если у него нет назначенных инициализаторов. – Olaf

+0

Этот ответ неверен. аналогично C99-соединению, но это определенно не одно. –