C vs. C++: non-trivial designated initializers not supported

B

Balog Pal

Francesco S. Carta said:
What is so ugly with the "no initialized + assignment" approach suggested
by Andrey?

As Johannes stated in the part you cut out, that stuff goes to a const
segment sitting in ROM, so assignment does not play, only static init.

The part I don't get is why providing initializer for all struct members
(either literally, or better yet using a macro) is so painful. Such tables
are routinely created using macros. (For those unfamiliar with embedded,
you start work by including a few hundred kByte header with half content
being #define... so using a few more hardly hurts ;-)
 
J

Jorgen Grahn

Am 29.07.2010 20:56, schrieb Richard:
[Please do not mail me a copy of your followup]

James Kanze <[email protected]> spake the secret code
PODObject vectorTable = {
FunctionValue: MyFunctionImpl,
};

I don't know what this is, but its not syntactically valid C or C++.

It's valid C99.

Apparently not. The syntax is .member = initializer, not
member: initializer.

Yes, I used the deprecated variant. Is there anything like this in C++?

The "deprecated variant" was, as far as I can tell a GCC extension to
the C language, not something that was ever part of the language. The
manual says it's obsolete since GCC 2.5 -- i.e. a really long time
ago.

I seem to recall the Linux kernel using 'FIELDNAME: value' at one point,
later switching to '.FIELDNAME = value'.

/Jorgen
 
J

Johannes Bauer

Am 30.07.2010 00:09, schrieb Balog Pal:
The part I don't get is why providing initializer for all struct members
(either literally, or better yet using a macro) is so painful.

Image you have 150 ISRs. You occupy only 3 of them, #17, #99 and #130.

This means you have to write

0, (16 times)
FirstISR,
0, (81 times)
SecondISR,
0, (30 times)
ThirdISR,
0, (20 times)

Calculating these numbers by oneself is incredibly error-prone. Even
worse: If you're off-by-one (as I actually was when I first wrote these
lines) you will not get any error, but it will rain crap during runtime.

It is much less error prone to write:

..USART_RXC = FirstISR,
..Ethernet_RXC = SecondISR,
..ExternalIRQ = ThirdISR

and not have to worry about the actual positions.

Furthermore, say you insert one beween #2 and #3 (say at 104). Then you
have to split the "0, (30 times)" up (into 4 + 25) which is even more
error-prone.
Such
tables are routinely created using macros. (For those unfamiliar
with embedded, you start work by including a few hundred kByte header
with half content being #define... so using a few more hardly hurts ;-)

If you knew a way to do this with macros, I'd be fine with it. However
nobody here has come up with a solution to make this problem work with
C++ (either using macros or not). I start to believe there may be no way
to solve that using C++ (which is IMHO, a pity, considering that C can
do it with ease).

Regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
F

Francesco S. Carta

Am 30.07.2010 00:09, schrieb Balog Pal:


Image you have 150 ISRs. You occupy only 3 of them, #17, #99 and #130.

This means you have to write

0, (16 times)
FirstISR,
0, (81 times)
SecondISR,
0, (30 times)
ThirdISR,
0, (20 times)

Calculating these numbers by oneself is incredibly error-prone. Even
worse: If you're off-by-one (as I actually was when I first wrote these
lines) you will not get any error, but it will rain crap during runtime.

It is much less error prone to write:

.USART_RXC = FirstISR,
.Ethernet_RXC = SecondISR,
.ExternalIRQ = ThirdISR

and not have to worry about the actual positions.

Furthermore, say you insert one beween #2 and #3 (say at 104). Then you
have to split the "0, (30 times)" up (into 4 + 25) which is even more
error-prone.


If you knew a way to do this with macros, I'd be fine with it. However
nobody here has come up with a solution to make this problem work with
C++ (either using macros or not). I start to believe there may be no way
to solve that using C++ (which is IMHO, a pity, considering that C can
do it with ease).

If plain source code size is not a problem, you can do:

PODObject pod = {
0, // #0 member name
0, // #1 member name
0, // #2 member name
// ...
0 // #149 member name
}

And set just what you need wherever you need it, in this way you can be
sure you won't mess up the list.

Otherwise, if you think you can get the number of intervening unused
members right, you can create macros like this:

#define Z_5 0, 0, 0, 0, 0
#define Z_10 Z_5, Z_5
#define Z_20 Z_10, Z_10
#define Z_25 Z_20, Z_5
#define Z_50 Z_25, Z_25
#define Z_100 Z_50, Z_50

and use them like this:

PODObject pod = {
Z_50, Z_20,
42,
Z_10, 0, 0,
78
}

I know, it's ugly and hard to maintain, but it's better than writing and
counting zeroes by hand, and personally I would really use the complete
(commented) initialization list I mentioned above, seen that I found no
better C++ solution in the context at hand.
 
R

Richard

[Please do not mail me a copy of your followup]

Johannes Bauer <[email protected]> spake the secret code
If you knew a way to do this with macros, I'd be fine with it.

I don't understand the difficulty here. I'd write a macro that takes
the non-zero elements of the initializer and supplies all the zero
elements. Its really not that hard:

#define INITIALIZE(first_, second_, third_) \
{ \
first_, 0, 0, 0, 0, \
second_, 0, 0, 0, 0, \
third_ \
}

etc.

HugeStruct s = INITIALIZE(10, 20, 30);

I've done this before when initializing structs with huge initializer
lists; its really no big deal.

I believe that any unspecified initializers at the end of the list will
automatically be filled with zero, so there's no need to specify them
explicitly.
 
J

James Kanze

Am 30.07.2010 00:09, schrieb Balog Pal:
Image you have 150 ISRs. You occupy only 3 of them, #17, #99 and #130.
This means you have to write
0, (16 times)
FirstISR,
0, (81 times)
SecondISR,
0, (30 times)
ThirdISR,
0, (20 times)
Calculating these numbers by oneself is incredibly
error-prone. Even worse: If you're off-by-one (as I actually
was when I first wrote these lines) you will not get any
error, but it will rain crap during runtime.

While I do think that adding the designated initializer syntax
to C++ would have been useful, in this particular case, I don't
see any real problem. It would take less than ten minutes to
write a small script in AWK which generates the full initializer
list, given the structure definition (supposing it is formatted
according to some established convention) and a list of the
concerned elements with their initializer.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top