Подтвердить что ты не робот

Нечетный синтаксис в С++: return {.name = value,...}

При чтении статьи я столкнулся со следующей функцией:

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,
  };
}

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

Изменить: ссылка на оригинальную статью

4b9b3361

Ответ 1

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

Он (вроде) использует пару функций из 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;
}

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

Ответ 2

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

6.26 Составные литералы

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