Discussion:
C vs. C++: non-trivial designated initializers not supported
(too old to reply)
Johannes Bauer
2010-07-29 16:57:58 UTC
Permalink
Hello group,

I know this might be an implementation detail - however I do not
understand why the languages C++ and C are different in the following
example - I'm quite stunned and am looking for an explanation. Writing
some code and porting from C to C++ I encountered the error "sorry,
unimplemented: non-trivial designated initializers not supported" from
g++ 4.3.4. I boiled it down to a minimal example which compiles fine
under C, but emits that error message when compiled under C++:

typedef void (*FunctionType)(void);

typedef struct PODObject {
void *PointerValue;
FunctionType FunctionValue;
} PODObject;

void MyFunctionImpl(void);

PODObject vectorTable = {
FunctionValue: MyFunctionImpl,
};

void MyFunctionImpl() {
}


I have three options to make the code compile even when using C++:
1. Comment out the void* declaration of the PODObject
2. Change the order or PointerValue and FunctionValue
3. Define PointerValue in the struct definition

However, none of these options are really applicable in this particular
case. Is there a possibility or workaround or completely different
approach which lets me do the same thing as C does (i.e. fill the
undefined struct values with some random undefined data)?

Regards,
Johannes
--
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
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 <hidbv3$om2$***@speranza.aioe.org>
legalize+ (Richard)
2010-07-29 17:08:21 UTC
Permalink
[Please do not mail me a copy of your followup]
Post by Johannes Bauer
PODObject vectorTable = {
FunctionValue: MyFunctionImpl,
};
I don't know what this is, but its not syntactically valid C or C++.
--
"The Direct3D Graphics Pipeline" -- DirectX 9 draft available for download
<http://legalizeadulthood.wordpress.com/the-direct3d-graphics-pipeline/>

Legalize Adulthood! <http://legalizeadulthood.wordpress.com>
Johannes Bauer
2010-07-29 17:12:14 UTC
Permalink
Post by legalize+ (Richard)
[Please do not mail me a copy of your followup]
Post by Johannes Bauer
PODObject vectorTable = {
FunctionValue: MyFunctionImpl,
};
I don't know what this is, but its not syntactically valid C or C++.
Are you sure? "gcc -Wall -Wextra -O2 -ansi -pedantic -c i.c" complains
only that it is an old form:

i.c:11: warning: obsolete use of designated initializer with ‘:’

However, it compiles, even with -ansi -pedantic. Therefore I doubt that
it's as far off the standard as your reply implies.

Regards,
Johannes
--
Post by legalize+ (Richard)
Post by Johannes Bauer
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
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 <hidbv3$om2$***@speranza.aioe.org>
Balog Pal
2010-07-29 17:31:29 UTC
Permalink
Post by Johannes Bauer
i.c:11: warning: obsolete use of designated initializer with ‘:’
However, it compiles, even with -ansi -pedantic. Therefore I doubt that
it's as far off the standard as your reply implies.
Designated init is definitely NOT in the C++ standard. The compiler emitted
a diagnostic for your ill-formed code, so it compiled the requirements, the
content of the message and what happens otherwise is a different issue.

More bad news: designated init is not in C++0x either. (Though there is
fairly enhanced {} init...)

If you want portable C++, do something else. If you're happy with what g++
does, it is an option too.
Johannes Bauer
2010-07-29 17:31:47 UTC
Permalink
Post by Balog Pal
Post by Johannes Bauer
i.c:11: warning: obsolete use of designated initializer with ‘:’
However, it compiles, even with -ansi -pedantic. Therefore I doubt that
it's as far off the standard as your reply implies.
Designated init is definitely NOT in the C++ standard. The compiler
emitted a diagnostic for your ill-formed code, so it compiled the
requirements, the content of the message and what happens otherwise is a
different issue.
You read me wrong. The gcc C compiler compiles the code (even with
-std=c89) and emits a diagnostic.

The g++ C++ compiler does not compile the code at all. I'm just
wondering about this (since it is pretty basic stuff, putting a struct
somewhere and having it initialized with some values).
Post by Balog Pal
More bad news: designated init is not in C++0x either. (Though there is
fairly enhanced {} init...)
If you want portable C++, do something else. If you're happy with what
g++ does, it is an option too.
Well, g++ doesn't compile it - so that's not really an option. The most
interesting question you did not answer, however: How would you
formulate the requirement in portable C? C++0x is an option, I wouldn't
mind using C++0x features.

Regards,
Johannes
--
Post by Balog Pal
Post by Johannes Bauer
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
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 <hidbv3$om2$***@speranza.aioe.org>
legalize+ (Richard)
2010-07-29 18:28:50 UTC
Permalink
[Please do not mail me a copy of your followup]
Post by Johannes Bauer
Post by legalize+ (Richard)
[Please do not mail me a copy of your followup]
Post by Johannes Bauer
PODObject vectorTable = {
FunctionValue: MyFunctionImpl,
};
I don't know what this is, but its not syntactically valid C or C++.
Are you sure?
No. That's why I said I don't know what it is. To me it looks like a
label declaration in the middle of an aggregate initializer, which is
why I didn't think it was syntactically valid C or C++.

I didn't know about designated initializers in C99. I have been using
C++ since 1990 and haven't been following C standardization beyond
that time.

So, it turns out that for (some flavors) of C, its syntactically
valid. However, I don't see anything that indicates its ever
syntactically valid C++.

At any rate, I don't see the value added here.

From looking at other posts and [1], even the syntax used here is
wrong. So its not even syntactically valid C99.

[1]
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/designators.htm
--
"The Direct3D Graphics Pipeline" -- DirectX 9 draft available for download
<http://legalizeadulthood.wordpress.com/the-direct3d-graphics-pipeline/>

Legalize Adulthood! <http://legalizeadulthood.wordpress.com>
James Kanze
2010-07-29 18:39:32 UTC
Permalink
Post by legalize+ (Richard)
Post by Johannes Bauer
PODObject vectorTable = {
FunctionValue: MyFunctionImpl,
};
I don't know what this is, but its not syntactically valid C or C++.
It's valid C99. C++ is based on C90 (but the next version
didn't adopt this from C either---I don't know why not).

--
James Kanze
legalize+ (Richard)
2010-07-29 18:56:53 UTC
Permalink
[Please do not mail me a copy of your followup]
Post by James Kanze
Post by legalize+ (Richard)
Post by Johannes Bauer
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.
--
"The Direct3D Graphics Pipeline" -- DirectX 9 draft available for download
<http://legalizeadulthood.wordpress.com/the-direct3d-graphics-pipeline/>

Legalize Adulthood! <http://legalizeadulthood.wordpress.com>
Johannes Bauer
2010-07-29 20:50:39 UTC
Permalink
Post by legalize+ (Richard)
[Please do not mail me a copy of your followup]
Post by James Kanze
Post by legalize+ (Richard)
Post by Johannes Bauer
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++?

Kind regards,
Johannes
--
Post by legalize+ (Richard)
Post by James Kanze
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
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 <hidbv3$om2$***@speranza.aioe.org>
Jorgen Grahn
2010-07-30 08:04:33 UTC
Permalink
Post by Johannes Bauer
Post by legalize+ (Richard)
[Please do not mail me a copy of your followup]
Post by James Kanze
Post by legalize+ (Richard)
Post by Johannes Bauer
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
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Jonathan Lee
2010-07-29 17:11:03 UTC
Permalink
Post by Johannes Bauer
Hello group,
I know this might be an implementation detail - however I do not
understand why the languages C++ and C are different in the following
example - I'm quite stunned and am looking for an explanation.
Designated initializers are a C99 feature, if I remember correctly.
Several features of C99 did not make it into the C++ specification.
I don't know if this particular one was rejected, never proposed,
planned, etc. It could have just been a matter of timing (since
the original C++ specification was 1998).

I suspect, though, that the presence of constructors in C++
makes designated initializers mostly pointless.
Post by Johannes Bauer
  1. Comment out the void* declaration of the PODObject
  2. Change the order or PointerValue and FunctionValue
  3. Define PointerValue in the struct definition
Use #ifdef __cplusplus? It's ugly, but what do you expect
when mixing two different languages?

PODObject vectorTable = {
#ifdef __cplusplus
NULL, MyFunctionImpl
#else
FunctionValue: MyFunctionImpl
#endif
};
Post by Johannes Bauer
However, none of these options are really applicable in this particular
case. Is there a possibility or workaround or completely different
approach which lets me do the same thing as C does (i.e. fill the
undefined struct values with some random undefined data)?
Of course, if you dropped the requirement for uninitialized data
you could just fill in the first field with NULL. I highly doubt
it will create a performance hit...

--Jonathan
Johannes Bauer
2010-07-29 17:20:01 UTC
Permalink
Post by Jonathan Lee
Post by Johannes Bauer
Hello group,
I know this might be an implementation detail - however I do not
understand why the languages C++ and C are different in the following
example - I'm quite stunned and am looking for an explanation.
Designated initializers are a C99 feature, if I remember correctly.
Several features of C99 did not make it into the C++ specification.
I don't know if this particular one was rejected, never proposed,
planned, etc. It could have just been a matter of timing (since
the original C++ specification was 1998).
Hmm - actually it compiles with only a warning with -ansi -pedantic
-std=c89 (warning: obsolete use of designated initializer with ‘:’)
Post by Jonathan Lee
Use #ifdef __cplusplus? It's ugly, but what do you expect
when mixing two different languages?
PODObject vectorTable = {
#ifdef __cplusplus
NULL, MyFunctionImpl
#else
FunctionValue: MyFunctionImpl
#endif
};
Well, actually the point of it all was that not all fields need to be
specified. The actual vectorTable contains >150 entries of which only
about 10 will be filled usually. The point of the whole construct was so
the unused fields can be omitted.
Post by Jonathan Lee
Post by Johannes Bauer
However, none of these options are really applicable in this particular
case. Is there a possibility or workaround or completely different
approach which lets me do the same thing as C does (i.e. fill the
undefined struct values with some random undefined data)?
Of course, if you dropped the requirement for uninitialized data
you could just fill in the first field with NULL. I highly doubt
it will create a performance hit...
No, initialized data is fine (viewing initialized data as a subset of
uninitialized data). Anything which was omitted may well be set to 0 or
0xffffffff or whatever the compiler likes - if it only would allow me to
omit it (like the C compiler does).

Regards,
Johannes
--
Post by Jonathan Lee
Post by Johannes Bauer
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
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 <hidbv3$om2$***@speranza.aioe.org>
Jonathan Lee
2010-07-29 17:38:49 UTC
Permalink
Post by Johannes Bauer
Well, actually the point of it all was that not all fields need to be
specified. The actual vectorTable contains >150 entries of which only
about 10 will be filled usually.
Ouch. Er... in that case I guess you'd have to declare the variable
without an initializer (or rely on zero initialization) and then set
them one by one.

I don't really have a better solution than that. (Other than, you know
140+ unused fields sounds like a struct that wants to be rewritten...)

--Jonathan
Johannes Bauer
2010-07-29 20:47:53 UTC
Permalink
Post by Jonathan Lee
Post by Johannes Bauer
Well, actually the point of it all was that not all fields need to be
specified. The actual vectorTable contains >150 entries of which only
about 10 will be filled usually.
Ouch. Er... in that case I guess you'd have to declare the variable
without an initializer (or rely on zero initialization) and then set
them one by one.
I don't really have a better solution than that. (Other than, you know
140+ unused fields sounds like a struct that wants to be rewritten...)
:-/

That seems to suck, is there really no other way? I cannot change the
initializers at runtime as the struct needs to be laid out in advance
and is placed in ROM (actually Flash, but ROM for that purpose).

Maybe I'll just use C-code for that part (with the correct ".foo = bar"
syntax of course) and mix the two languages. I'd really like to have
done it all in C++, though.

Regards,
Johannes
--
Post by Jonathan Lee
Post by Johannes Bauer
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
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 <hidbv3$om2$***@speranza.aioe.org>
Jonathan Lee
2010-07-29 21:14:09 UTC
Permalink
Post by Johannes Bauer
Post by Jonathan Lee
Ouch. Er... in that case I guess you'd have to declare the variable
without an initializer (or rely on zero initialization) and then set
them one by one.
:-/
That seems to suck, is there really no other way? I cannot change the
initializers at runtime as the struct needs to be laid out in advance
and is placed in ROM (actually Flash, but ROM for that purpose).
The only other thing I can think of is to simply do this stuff in C
source and build that part of the tree with the C compiler :/

--Jonathan
Andrey Tarasevich
2010-07-29 17:53:24 UTC
Permalink
Post by Johannes Bauer
Well, actually the point of it all was that not all fields need to be
specified. The actual vectorTable contains >150 entries of which only
about 10 will be filled usually. The point of the whole construct was so
the unused fields can be omitted.
If this is a _maintenance_ issue, then the way to do it portably is to
define the struct object without any initializer at all and then use
_assignment_ to set some specific fields.

If this is a _performance_ issue, the initializers will not help you
here, since in C (and in similar context in C++), initializing just one
field of the struct automatically triggers zero-initialization for _all_
fields of the struct. I.e. if you want to leave all other fields
uninitialized (for performance reasons), the way to go is again to
define the struct object without any initializer at all and then use
assignment to set some specific fields.
Post by Johannes Bauer
No, initialized data is fine (viewing initialized data as a subset of
uninitialized data). Anything which was omitted may well be set to 0 or
0xffffffff or whatever the compiler likes - if it only would allow me to
omit it (like the C compiler does).
Like _C99_ compiler does. If you want your code to be portable across
C89/90, C99 and C++ you have no other choice but to use either "no
initializer+assignment" approach or "supply all initializers beginning
from the first" approach.
--
Best regards,
Andrey Tarasevich
Johannes Bauer
2010-07-29 20:46:15 UTC
Permalink
Post by Andrey Tarasevich
Post by Johannes Bauer
Well, actually the point of it all was that not all fields need to be
specified. The actual vectorTable contains >150 entries of which only
about 10 will be filled usually. The point of the whole construct was so
the unused fields can be omitted.
If this is a _maintenance_ issue, then the way to do it portably is to
define the struct object without any initializer at all and then use
_assignment_ to set some specific fields.
This is not possible. The code is part of a IVT and therefore needs to
be laid out by the compiler to contain the function addresses of the ISRs.
Post by Andrey Tarasevich
If this is a _performance_ issue, the initializers will not help you
here, since in C (and in similar context in C++), initializing just one
field of the struct automatically triggers zero-initialization for _all_
fields of the struct. I.e. if you want to leave all other fields
uninitialized (for performance reasons), the way to go is again to
define the struct object without any initializer at all and then use
assignment to set some specific fields.
No, see above.
Post by Andrey Tarasevich
Post by Johannes Bauer
No, initialized data is fine (viewing initialized data as a subset of
uninitialized data). Anything which was omitted may well be set to 0 or
0xffffffff or whatever the compiler likes - if it only would allow me to
omit it (like the C compiler does).
Like _C99_ compiler does. If you want your code to be portable across
C89/90, C99 and C++ you have no other choice but to use either "no
initializer+assignment" approach or "supply all initializers beginning
from the first" approach.
Well, that's no real nice solution. The struct has around 150 actual ISR
handlers and I want to set some specific ones without having to know
where they all need to be placed in memory.

Regards,
Johannes
--
Post by Andrey Tarasevich
Post by Johannes Bauer
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
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 <hidbv3$om2$***@speranza.aioe.org>
Francesco S. Carta
2010-07-29 21:48:17 UTC
Permalink
Post by Johannes Bauer
Post by Andrey Tarasevich
Post by Johannes Bauer
No, initialized data is fine (viewing initialized data as a subset of
uninitialized data). Anything which was omitted may well be set to 0 or
0xffffffff or whatever the compiler likes - if it only would allow me to
omit it (like the C compiler does).
Like _C99_ compiler does. If you want your code to be portable across
C89/90, C99 and C++ you have no other choice but to use either "no
initializer+assignment" approach or "supply all initializers beginning
from the first" approach.
Well, that's no real nice solution. The struct has around 150 actual ISR
handlers and I want to set some specific ones without having to know
where they all need to be placed in memory.
What is so ugly with the "no initialized + assignment" approach
suggested by Andrey?

This chunk of code isn't all that hard to type or to review, is valid
everywhere (within the context at hand) and, IIUIC, should also be
faster than the C99 version mentioned in the OP:

//-------
PODObject obj;
obj.FunctionValue = MyFunctionImpl;
//-------


And if one really wants a one-liner, one can always take advantage
(grin) of the preprocessor:

//-------
#define CREATEPOD(obj_name, member_name, value) \
PODObject obj_name; \
obj_name.member_name = value;

typedef void(*FunctionType)();

struct PODObject {
void* PointerValue;
FunctionType FunctionValue;
};

void MyFunctionImpl() {}

int main() {
CREATEPOD(obj, FunctionValue, MyFunctionImpl);
obj.FunctionValue();
}
//-------

For the records, I wouldn't use macros, I would just use the two lines I
mentioned first.
--
FSC - http://userscripts.org/scripts/show/59948
http://fscode.altervista.org - http://sardinias.com
Balog Pal
2010-07-29 22:09:21 UTC
Permalink
Post by Johannes Bauer
Well, that's no real nice solution. The struct has around 150 actual ISR
handlers and I want to set some specific ones without having to know
where they all need to be placed in memory.
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 ;-)
Francesco S. Carta
2010-07-29 22:07:36 UTC
Permalink
Post by Balog Pal
Post by Francesco S. Carta
Post by Johannes Bauer
Well, that's no real nice solution. The struct has around 150 actual ISR
handlers and I want to set some specific ones without having to know
where they all need to be placed in memory.
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.
Sorry, I overlooked that part.
--
FSC - http://userscripts.org/scripts/show/59948
http://fscode.altervista.org - http://sardinias.com
Johannes Bauer
2010-07-30 15:06:48 UTC
Permalink
Post by 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.
Post by Balog Pal
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
--
Post by Balog Pal
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
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 <hidbv3$om2$***@speranza.aioe.org>
Francesco S. Carta
2010-07-30 15:50:49 UTC
Permalink
Post by Johannes Bauer
Post by 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.
.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.
Post by Balog Pal
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).
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.
--
FSC - http://userscripts.org/scripts/show/59948
http://fscode.altervista.org - http://sardinias.com
legalize+ (Richard)
2010-07-30 17:01:40 UTC
Permalink
[Please do not mail me a copy of your followup]
Post by Johannes Bauer
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.
--
"The Direct3D Graphics Pipeline" -- DirectX 9 draft available for download
<http://legalizeadulthood.wordpress.com/the-direct3d-graphics-pipeline/>

Legalize Adulthood! <http://legalizeadulthood.wordpress.com>
James Kanze
2010-07-31 12:18:21 UTC
Permalink
Post by Johannes Bauer
Post by 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.
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.

--
James Kanze

Andrey Tarasevich
2010-07-29 17:45:27 UTC
Permalink
Post by Johannes Bauer
I know this might be an implementation detail - however I do not
understand why the languages C++ and C are different in the following
example - I'm quite stunned and am looking for an explanation.
C++ language does not have "designated initializers", neither trivial
nor non-trivial. The same applies to C89/90 version of C language. If
you only care to initialize one specific field with an aggregate
initializer, you have to supply _all_ initializers, beginning form the
first, until you reach the field in question. The rest of the
initializers can be omitted (meaning that the rest of the struct will be
implicitly zero-initialized).
Post by Johannes Bauer
PODObject vectorTable = {
FunctionValue: MyFunctionImpl,
};
"Designated initializers" is a feature of C99 version of C language and
the proper syntax is as follows

PODObject vectorTable = { .FunctionValue = MyFunctionImpl };
Post by Johannes Bauer
1. Comment out the void* declaration of the PODObject
??? It is not clear what you mean here.
Post by Johannes Bauer
2. Change the order or PointerValue and FunctionValue
Well, as a way to make your code shorter, it will work (see below)
Post by Johannes Bauer
3. Define PointerValue in the struct definition
??? It is not clear what you mean here.

You have the 4th way: just do it the way it has been done for ages,
without any "designated initializers". Just supply all preceding
initializers explicitly

PODObject vectorTable = { 0, MyFunctionImpl };

Your 2nd approach is just a way to get rid of that explicit leading 0.
Post by Johannes Bauer
However, none of these options are really applicable in this particular
case. Is there a possibility or workaround or completely different
approach which lets me do the same thing as C does (i.e. fill the
undefined struct values with some random undefined data)?
"Undefined struct values" do not get filled with "random undefined
data". C language follows all-or-noting approach to initialization. If
you initialize just some of the struct fields (regardless of whether you
use designated initializers or not), the rest gets implicitly zero
initialized for you.
--
Best regards,
Andrey Tarasevich
Johannes Bauer
2010-07-29 20:54:00 UTC
Permalink
Post by Andrey Tarasevich
Post by Johannes Bauer
I know this might be an implementation detail - however I do not
understand why the languages C++ and C are different in the following
example - I'm quite stunned and am looking for an explanation.
C++ language does not have "designated initializers", neither trivial
nor non-trivial. The same applies to C89/90 version of C language. If
you only care to initialize one specific field with an aggregate
initializer, you have to supply _all_ initializers, beginning form the
first, until you reach the field in question. The rest of the
initializers can be omitted (meaning that the rest of the struct will be
implicitly zero-initialized).
Post by Johannes Bauer
PODObject vectorTable = {
FunctionValue: MyFunctionImpl,
};
"Designated initializers" is a feature of C99 version of C language and
the proper syntax is as follows
PODObject vectorTable = { .FunctionValue = MyFunctionImpl };
Post by Johannes Bauer
1. Comment out the void* declaration of the PODObject
??? It is not clear what you mean here.
When I leave out the member "PointerValue" from the struct, it works
(since all are initialized then).
Post by Andrey Tarasevich
Post by Johannes Bauer
2. Change the order or PointerValue and FunctionValue
Well, as a way to make your code shorter, it will work (see below)
Well, it's not possible to change the order in my case (since the layout
of the struct is determined by hardware, not by me).
Post by Andrey Tarasevich
Post by Johannes Bauer
3. Define PointerValue in the struct definition
??? It is not clear what you mean here.
If I define PointerValue, like say to 0...
Post by Andrey Tarasevich
You have the 4th way: just do it the way it has been done for ages,
without any "designated initializers". Just supply all preceding
initializers explicitly
PODObject vectorTable = { 0, MyFunctionImpl };
...like you did here, then it also works. However, I really do not want
to have to use NULL 140 times and know exactly at what positions I need
to fill the proper ISR function pointers.
Post by Andrey Tarasevich
Your 2nd approach is just a way to get rid of that explicit leading 0.
Post by Johannes Bauer
However, none of these options are really applicable in this particular
case. Is there a possibility or workaround or completely different
approach which lets me do the same thing as C does (i.e. fill the
undefined struct values with some random undefined data)?
"Undefined struct values" do not get filled with "random undefined
data". C language follows all-or-noting approach to initialization. If
you initialize just some of the struct fields (regardless of whether you
use designated initializers or not), the rest gets implicitly zero
initialized for you.
What I meant was: It could even be filled with random data. I do not
rely on it being initialized to anything, as the data is never read
during runtime.

Regards,
Johannes
--
Post by Andrey Tarasevich
Post by Johannes Bauer
Wo hattest Du das Beben nochmal GENAU vorhergesagt?
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 <hidbv3$om2$***@speranza.aioe.org>
Loading...