22

While reading an article, I came across the following function:

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

What is the author doing with the return statement? I haven't seen anything like that before, and I do not know how to search for it... Is it valid for plain C too?

Edit: link to the original article

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 5
    Valid in C, non-standard extension of some compilers for C++ (as of C++11, this functionality is not in the C++ standard.) – Dark Falcon Jul 23 '15 at 17:21
  • 2
    See [the C standard](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf), section _6.5.2.5 Compound literals_, point 10 (regarding designated initializers). – Michael Jul 23 '15 at 17:21
  • 1
    I'm pretty sure that's valid for plain C, and _not_ valid for C++. – davmac Jul 23 '15 at 17:21
  • Note, sure why this was reopened, there are many duplcates for this question, here is [another one](http://stackoverflow.com/q/19272205/1708801) and I am sure we can find many more such as the one that Dark Falcon found cc @JerryCoffin – Shafik Yaghmour Jul 23 '15 at 17:29
  • 1
    @ShafikYaghmour: there may be many duplicates, but the nominated one wasn't really (even close to) a duplicate--it was asking *why* C++ doesn't have designated intializers (and the answers were pretty much restricted to the question of why). This is asking about what the syntax *means*, not why it isn't present in C++. The one you've found is at least reasonably close to being a duplicate (but at least IMO, when closing as a duplicate, it's important not to just close, but to be sure the answers to the nominated duplicate really answer the question being asked here). – Jerry Coffin Jul 23 '15 at 17:32
  • @JerryCoffin yes, upon a closer read it was not a perfect duplicate but there are surely closer ones that could have been found before reopening and use a closer one as a duplicate. – Shafik Yaghmour Jul 23 '15 at 17:34
  • 1
    @Michael: A _compound literal_ would require a parenthtised type before the `{`. And desgnated initializers are not standard C++ (but - afaik - gcc allows them for C++, too as extension). – too honest for this site Jul 23 '15 at 17:37
  • 1
    @ShafikYaghmour: If you can find a real dupe, I (for one) will be happy to vote to close as a dupe--but neither that's been nominated so far strikes me as a sufficiently good fit. The first was way off, and while the second is closer, it's still not quite right (see my answer for more about the deviation from compound literal syntax that's not covered in the other questions/answers. – Jerry Coffin Jul 23 '15 at 17:40
  • Sorry for the possible duplicate, but when you have never seen something like that before, cannot describe it, cannot understand surely what it does etc etc, how to search for it?... – Fotis Panagiotopoulos Jul 23 '15 at 17:40
  • 1
    @user3634713: Yes--I don't think anybody's "blaming" you for asking the question, or anything similar. At the same, Shafik Yaghmour is right that if the same question has been asked before (and has good answers) we'd prefer to link to that question rather than have the same question with different answers in different places. When closed as a duplicate, your question remains in the system so Google (for example) can still find it, so it still provides real value. – Jerry Coffin Jul 23 '15 at 17:42
  • @user3634713: That article starts with a wrong prerequisite even: The STM32F42**7** does not even have an LCD-controller or graphic engine. That would be the STM32F42**9**. IMO this is a bad start to accept what was written otherwise. – too honest for this site Jul 23 '15 at 17:42
  • Jerry is correct, I am not sure how you would search for this, duplicates are a natural part of the system. – Shafik Yaghmour Jul 23 '15 at 17:45
  • @Olaf You completelly missed the point, which was exactly that. To produce "software" graphics, on a MCU without specialized hardware. I consider the article interesting, as for its very careful (and to the limit) use of the DMA. – Fotis Panagiotopoulos Jul 23 '15 at 17:49
  • @user3634713: I did certainly **not** miss the point; I actually know the STM32F4xx family very well. You did not get **my** point however. As the article already starts with such a basic flaw, I would be concerned about other aspects it states and how reliable these are. As for the stub you ask about. For "procuding graphics on an MCU without "specialized hardware": I did that more than 20 years ago on a 86HC11 with an LCD panel, inspired by the Sinclar ZX81 of the early 80ies. – too honest for this site Jul 23 '15 at 17:52
  • Ohh, I just found what you saw, because the article is basically for the STM32F407. This reference may be a typo or anything... I still don't care, and I mostly read it about the technique used. I wouldn't implement anything for a product by copy-pasting some code :). – Fotis Panagiotopoulos Jul 23 '15 at 17:58
  • @DarkFalcon this is not valid in C. The designated initializers are valid in C, but `return {` is not. – M.M Jul 24 '15 at 00:36

2 Answers2

21

This isn't valid C++.

It's (sort of) using a couple features from C known as "compound literals" and "designated initializers", which a few C++ compilers support as an extension. The "sort of" comes from that fact that to be a legitimate C compound literal, it should have syntax that looks like a cast, so you'd have something like:

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

Regardless of the difference in syntax, however, it's basically creating a temporary struct with members initialized as specified in the block, so this is roughly equivalent to:

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

The big difference (as you can see) is that designated initializers allow you to use member names to specify what initializer goes to what member, rather than depending solely on the order/position.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Just `return { 0, 1, (_width-1)*4, 1000};` in C++11 works, no need for `r`. Which brings the C++ syntax closer to the C99 syntax, and makes the fusion of the two be the syntax used above. – Yakk - Adam Nevraumont Jul 23 '15 at 18:26
9

It is a C99 compound literal. This feature is specific to C99, but gcc and clang choose to implement it in C++ as well(as extension).

6.26 Compound Literals

ISO C99 supports compound literals. A compound literal looks like a cast containing an initializer. Its value is an object of the type specified in the cast, containing the elements specified in the initializer; it is an lvalue. As an extension, GCC supports compound literals in C90 mode and in C++, though the semantics are somewhat different in C++.

Nazar554
  • 4,105
  • 3
  • 27
  • 38