468,554 Members | 1,068 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,554 developers. It's quick & easy.

Initializing compound type containing opaque type

Consider the following pseudo-code:

#include <opaque.h>

struct foo {
int a;
opaque_t op;
int b;
};

struct foo blah = { 17, /* ??? */ , 23 };

Here we suppose that `opaque_t' is defined in <opaque.has some type
not known to us, or which we cannot rely on. In particular, it may be
a scalar or compound type. The goal is to initialize `blah' in such a
way that `blah.a == 17' and `blah.b == 23'. We don't care about the
value of `blah.op'.

It seems to me that there is no way to do this in standard C. Is this
correct, or am I missing something?

A workaround would be to rearrange the members of `struct foo' as

struct foo2 {
int a;
int b;
opaque_t op;
};

struct foo2 blah2 = { 17, 23 };

I believe this is legal, but I could be wrong. My compiler warns
about a missing initializer, but accepts the code.

If `opaque_t' is known to be a compound type, we could write

struct foo blah3 = { 17, { }, 23 };

which again provokes a missing initializer warning but is accepted.
Again I am curious whether it is actually legal.

I thought of this issue after reading a post here a couple weeks ago,
"Exception handling crashes or exits" by Fabiano Sidler,
<48**********@news.bluewin.ch>, in which the poster wants a struct
with a jmp_buf as one member. He initializes that member with { 0 },
which is certainly non-portable. But I wondered if there is a
portable way to do the same thing.

If not, it seems like it might be useful for the authors of <opaque.h>
to provide a macro which is suitable as an initializer for opaque_t.
E.g. <opaque.hmight contain

typedef opaque_t struct {
int x,
double d;
};

#define OPAQUE_INITIALIZER { 0, 0.0 }

so that one could write

struct foo blah = { 17, OPAQUE_INITIALIZER, 23 };

In particular, this could be a useful extension for library authors to
provide for opaque library types (e.g. jmp_buf, FILE, etc).

Any thoughts?
Oct 1 '08 #1
27 2208
On Oct 2, 12:05 am, Nate Eldredge <n...@vulcan.lanwrote:
Consider the following pseudo-code:

#include <opaque.h>

struct foo {
int a;
opaque_t op;
int b;

};

struct foo blah = { 17, /* ??? */ , 23 };

Here we suppose that `opaque_t' is defined in <opaque.has some type
not known to us, or which we cannot rely on. In particular, it may be
a scalar or compound type. The goal is to initialize `blah' in such a
way that `blah.a == 17' and `blah.b == 23'. We don't care about the
value of `blah.op'.

It seems to me that there is no way to do this in standard C. Is this
correct, or am I missing something?

A workaround would be to rearrange the members of `struct foo' as

struct foo2 {
int a;
int b;
opaque_t op;

};

struct foo2 blah2 = { 17, 23 };

I believe this is legal, but I could be wrong. My compiler warns
about a missing initializer, but accepts the code.
Yes, it's legal.
(note: In POSIX it wouldn't be; *_t are reserved identifiers)
If `opaque_t' is known to be a compound type, we could write

struct foo blah3 = { 17, { }, 23 };

which again provokes a missing initializer warning but is accepted.
Again I am curious whether it is actually legal.
Also legal.
I thought of this issue after reading a post here a couple weeks ago,
"Exception handling crashes or exits" by Fabiano Sidler,
<48c4e24d$...@news.bluewin.ch>, in which the poster wants a struct
with a jmp_buf as one member. He initializes that member with { 0 },
which is certainly non-portable. But I wondered if there is a
portable way to do the same thing.
Yes, jmp_buf foo = {0};

Though that'd initialize all members to 0, 0.0 or NULL depending on
type, recursively applied for any aggregate
If not, it seems like it might be useful for the authors of <opaque.h>
to provide a macro which is suitable as an initializer for opaque_t.
Well, it is legal, so it's not useful.
E.g. <opaque.hmight contain
<snip>
Oct 1 '08 #2
Nate Eldredge wrote:
Consider the following pseudo-code:

#include <opaque.h>

struct foo {
int a;
opaque_t op;
int b;
};

struct foo blah = { 17, /* ??? */ , 23 };

Here we suppose that `opaque_t' is defined in <opaque.has some type
not known to us, or which we cannot rely on. In particular, it may be
a scalar or compound type. The goal is to initialize `blah' in such a
way that `blah.a == 17' and `blah.b == 23'. We don't care about the
value of `blah.op'.
In C99 you could use a "compound literal:"

struct foo blah = (struct foo){.a = 17, .b = 23};

(Double-check my syntax; I'm typing this hurriedly.)

In C90 you could initialize the unknown member to "zero of
the appropriate type:"

struct foo blah = { 17, { 0 }, 23 };

Some compilers may emit warnings for too few initializers, but
the initialization is valid; if opaque_t is compound, its sub-
elements are initialized to appropriate zeroes. The warnings may
be a nuisance, but they do no actual harm.

--
Er*********@sun.com
Oct 1 '08 #3
On Wed, 01 Oct 2008 14:05:53 -0700, Nate Eldredge <na**@vulcan.lan>
wrote:
>Consider the following pseudo-code:

#include <opaque.h>

struct foo {
int a;
opaque_t op;
int b;
};

struct foo blah = { 17, /* ??? */ , 23 };

Here we suppose that `opaque_t' is defined in <opaque.has some type
not known to us, or which we cannot rely on. In particular, it may be
a scalar or compound type. The goal is to initialize `blah' in such a
way that `blah.a == 17' and `blah.b == 23'. We don't care about the
value of `blah.op'.

It seems to me that there is no way to do this in standard C. Is this
correct, or am I missing something?

A workaround would be to rearrange the members of `struct foo' as

struct foo2 {
int a;
int b;
opaque_t op;
};

struct foo2 blah2 = { 17, 23 };

I believe this is legal, but I could be wrong. My compiler warns
about a missing initializer, but accepts the code.
An insufficient quantity of initializers is specifically allowed
(6.7.8-19 and -21). Compilers are allowed to issue diagnostic
messages for correct code. Some do so when assigning an int to a char
or when using gets. These are not so much warnings (a term not
defined in the standard) but more like reminders to the programmer
that something is "unusual" and worth a second look. As long as the
code complies with the standard, the compiler is obligated to accept
it.
>
If `opaque_t' is known to be a compound type, we could write

struct foo blah3 = { 17, { }, 23 };

which again provokes a missing initializer warning but is accepted.
Again I am curious whether it is actually legal.

I thought of this issue after reading a post here a couple weeks ago,
"Exception handling crashes or exits" by Fabiano Sidler,
<48**********@news.bluewin.ch>, in which the poster wants a struct
with a jmp_buf as one member. He initializes that member with { 0 },
which is certainly non-portable. But I wondered if there is a
It is portable, for both aggregate and scalar objects. See 6.7.8-16,
-11, and -19.
>portable way to do the same thing.

If not, it seems like it might be useful for the authors of <opaque.h>
to provide a macro which is suitable as an initializer for opaque_t.
E.g. <opaque.hmight contain

typedef opaque_t struct {
int x,
double d;
};

#define OPAQUE_INITIALIZER { 0, 0.0 }

so that one could write

struct foo blah = { 17, OPAQUE_INITIALIZER, 23 };

In particular, this could be a useful extension for library authors to
provide for opaque library types (e.g. jmp_buf, FILE, etc).
{0} should suffice. If the object requires non-zero initialization,
the library should provide an initialization function.

--
Remove del for email
Oct 1 '08 #4
Eric Sosman <Er*********@sun.comwrites:
Nate Eldredge wrote:
>Consider the following pseudo-code:

#include <opaque.h>

struct foo {
int a;
opaque_t op;
int b;
};

struct foo blah = { 17, /* ??? */ , 23 };

Here we suppose that `opaque_t' is defined in <opaque.has some type
not known to us, or which we cannot rely on. In particular, it may be
a scalar or compound type. The goal is to initialize `blah' in such a
way that `blah.a == 17' and `blah.b == 23'. We don't care about the
value of `blah.op'.

In C99 you could use a "compound literal:"

struct foo blah = (struct foo){.a = 17, .b = 23};

(Double-check my syntax; I'm typing this hurriedly.)
My compiler says "error: initializer element is not constant". It
does work if it is moved inside a function, so that blah is auto, but
that's of course entirely different. (Anyway, in that case we could
just initialize blah.a and blah.b by hand.)
In C90 you could initialize the unknown member to "zero of
the appropriate type:"

struct foo blah = { 17, { 0 }, 23 };

Some compilers may emit warnings for too few initializers, but
the initialization is valid; if opaque_t is compound, its sub-
elements are initialized to appropriate zeroes. The warnings may
be a nuisance, but they do no actual harm.
Interesting, so the OP was correct after all. I never knew about
"zero of the appropriate type". I assumed that would be wrong if
opaque_t turned out to be a scalar type, or a compound whose first
member was also compound, but apparently not. Those clever language
designers, always one step ahead. :)

Thanks to all who replied.
Oct 1 '08 #5
On Oct 2, 12:05 am, Nate Eldredge <n...@vulcan.lanwrote:
Consider the following pseudo-code:

#include <opaque.h>

struct foo {
int a;
opaque_t op;
int b;

};

struct foo blah = { 17, /* ??? */ , 23 };

Here we suppose that `opaque_t' is defined in <opaque.has some type
not known to us, or which we cannot rely on. In particular, it may be
a scalar or compound type. The goal is to initialize `blah' in such a
way that `blah.a == 17' and `blah.b == 23'. We don't care about the
value of `blah.op'.

It seems to me that there is no way to do this in standard C. Is this
correct, or am I missing something?
Whoops, I forgot to reply to this question at my post.
In C99 you can.

struct foo blah = { .a = 17, .b = 23 };

Mr Sossman mentioned compound literals, but I'm unsure why he didn't
mention this which is even simpler.

You can also do this for array elements

char foo[2] = { .[1] = 'a' };
Oct 1 '08 #6
On Oct 2, 1:28 am, Eric Sosman <Eric.Sos...@sun.comwrote:
....
In C99 you could use a "compound literal:"

struct foo blah = (struct foo){.a = 17, .b = 23};

(Double-check my syntax; I'm typing this hurriedly.)
I think you mean

struct foo blah = *(struct foo[]){ { .a = 17, .b = 23 } };
Oct 1 '08 #7
Nate Eldredge <na**@vulcan.lanwrites:
Eric Sosman <Er*********@sun.comwrites:
>Nate Eldredge wrote:
>>Consider the following pseudo-code:

#include <opaque.h>

struct foo {
int a;
opaque_t op;
int b;
};

struct foo blah = { 17, /* ??? */ , 23 };

Here we suppose that `opaque_t' is defined in <opaque.has some type
not known to us, or which we cannot rely on. In particular, it may be
a scalar or compound type. The goal is to initialize `blah' in such a
way that `blah.a == 17' and `blah.b == 23'. We don't care about the
value of `blah.op'.

In C99 you could use a "compound literal:"

struct foo blah = (struct foo){.a = 17, .b = 23};

(Double-check my syntax; I'm typing this hurriedly.)
Not allowed, I think, at file scope.
My compiler says "error: initializer element is not constant".
Just use the "initialiser list" rather than providing a compound
literal. I.e. write:

struct foo blah = {.a = 17, .b = 23};

This works for file-scope declarations as well as block-scope ones.
It
does work if it is moved inside a function, so that blah is auto, but
that's of course entirely different.
Yes. 6.7.8 paragraph 13 permits an expression of "compatible
structure or union type" when the object has automatic storage. You
have to read though to paragraph 16 to get to the text:

"Otherwise, the initializer for an object that has aggregate or
union type shall be a brace-enclosed list of initializers..."

to see that a compound literal is not allowed as the sole "top-level"
initialiser for an object with static storage duration. At least that
is my explanation of your error message.

--
Ben.
Oct 1 '08 #8
vi******@gmail.com writes:
<snip>
You can also do this for array elements

char foo[2] = { .[1] = 'a' };
There's no dot. I.e.:

char foo[2] = { [1] = 'a' };

--
Ben.
Oct 1 '08 #9
vi******@gmail.com wrote:
[...]
Whoops, I forgot to reply to this question at my post.
In C99 you can.

struct foo blah = { .a = 17, .b = 23 };

Mr Sossman mentioned compound literals, but I'm unsure why he didn't
mention this which is even simpler.
Because I was (as I said) in a hurry, typing faster than
I was thinking. An insalubrious habit ...

--
Eric Sosman
es*****@ieee-dot-org.invalid
Oct 2 '08 #10
On 1 Oct, 22:05, Nate Eldredge <n...@vulcan.lanwrote:
Consider the following pseudo-code:

#include <opaque.h>

struct foo {
* * * *int a;
* * * *opaque_t op;
* * * *int b;

};
If opaque_t is truly opaque, and not specified
in opaque.h, then the compiler won't accept
this definition of struct foo. If the compiler
is accepting this, then the header is specifying
opaque_t completely, so (I would argue) has
misnamed it because it isn't opaque.
struct foo blah = { 17, /* ??? */ , 23 };

Here we suppose that `opaque_t' is defined in <opaque.has some type
not known to us, or which we cannot rely on.
I don't understand what you mean by "not known to us". If
the compiler can get the definition from opaque_t, then
you can, too! Am I using the word "opaque" in a
stricter sense than you? When I say opaque type,
I mean that the header contains no more than:
typedef struct opaque * opaque_t;
or just:
struct opaque;

<snip>
If not, it seems like it might be useful for the authors of <opaque.h>
to provide a macro which is suitable as an initializer for opaque_t.
E.g. <opaque.hmight contain

typedef opaque_t struct {
* * * * int x,
* * * * double d;

};
Is this an opaque type? It's got an int and
a double, so ... no, it's not. At least not
by my understanding of the word opaque.

Oct 2 '08 #11
On 2 Oct, 00:45, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
vipps...@gmail.com writes:

<snip>
You can also do this for array elements
char foo[2] = { .[1] = 'a' };

There's no dot. *I.e.:

* char foo[2] = { [1] = 'a' };
Is that C99? I thought that was a gnu extension.

Oct 2 '08 #12
William Pursell <bi**********@gmail.comwrites:
On 1 Oct, 22:05, Nate Eldredge <n...@vulcan.lanwrote:
>Consider the following pseudo-code:

#include <opaque.h>

struct foo {
* * * *int a;
* * * *opaque_t op;
* * * *int b;

};

If opaque_t is truly opaque, and not specified
in opaque.h, then the compiler won't accept
this definition of struct foo. If the compiler
is accepting this, then the header is specifying
opaque_t completely, so (I would argue) has
misnamed it because it isn't opaque.
By "opaque" I mean an object whose format and contents are not
intended to be used by the programmer, and are subject to change.
This is how I've heard it used in the past.

jmp_buf is an example. Certainly you can open up <setjmp.hand find
out how it is defined on your system; maybe it's a struct with a
member for each of your CPU's registers. But you can't use any of
that information in a portable program, since on another system, or a
later version of the same system, it may be defined differently, or
used differently by the library, so in a more general sense you don't
really "know" how it's defined. All you "know" about jmp_buf is that
you can create one using setjmp() and pass it to longjmp() later on.
From the programmer's point of view it's just a magic cookie.

Other examples in the standard library would be time_t and FILE.
div_t is a library type that I would not call opaque; it is documented
as being a struct with two members, `quot' and `rem', whose types and
meanings are well described and guaranteed to be the same in all
conforming implementations.

Oct 2 '08 #13
William Pursell <bi**********@gmail.comwrites:
On 2 Oct, 00:45, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
>vipps...@gmail.com writes:

<snip>
You can also do this for array elements
char foo[2] = { .[1] = 'a' };

There's no dot. *I.e.:

* char foo[2] = { [1] = 'a' };

Is that C99? I thought that was a gnu extension.
Yes, it is C99:

designation:
designator-list =

designator-list:
designator
designator-list designator

designator:
[ constant-expression ]
. identifier

--
Ben.
Oct 2 '08 #14
William Pursell wrote:
On 2 Oct, 00:45, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
....
> char foo[2] = { [1] = 'a' };

Is that C99? ...
Yes.

Oct 2 '08 #15
William Pursell <bi**********@gmail.comwrites:
On 1 Oct, 22:05, Nate Eldredge <n...@vulcan.lanwrote:
>Consider the following pseudo-code:

#include <opaque.h>

struct foo {
* * * *int a;
* * * *opaque_t op;
* * * *int b;

};

If opaque_t is truly opaque, and not specified
in opaque.h, then the compiler won't accept
this definition of struct foo. If the compiler
is accepting this, then the header is specifying
opaque_t completely, so (I would argue) has
misnamed it because it isn't opaque.
There are different kinds of opacity. Consider type FILE, defined in
<stdio.h>. That header must completely specify the type -- but code
that uses it is expected to depend only on the standard functions and
the fact that it's an object type.
>struct foo blah = { 17, /* ??? */ , 23 };

Here we suppose that `opaque_t' is defined in <opaque.has some type
not known to us, or which we cannot rely on.

I don't understand what you mean by "not known to us". If
the compiler can get the definition from opaque_t, then
you can, too!
Sure you *can* -- but then the next version of the library defines it
differently and your code breaks.

It's both common and reasonable to define an "opaque" type that's
completely defined in the header, just by *asking* authors of client
code not to cheat by peeking at its innards. (Which is not to say
that there aren't other reasonable approaches.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 2 '08 #16
Nick Keighley <ni******************@hotmail.comwrites:
On 2 Oct, 17:28, Keith Thompson <ks...@mib.orgwrote:

<snip>
>There are different kinds of opacity. *Consider type FILE, defined in
<stdio.h>. *That header must completely specify the type

why? user code only needs a pointer
>-- but code
that uses it is expected to depend only on the standard functions and
the fact that it's an object type.

<snip>
The standard requires FILE to be

an object type capable of recording all the information needed to
control a stream, including its file position indicator, a pointer
to its associated buffer (if any), an _error indicator_ that
records whether a read/write error has occurred, and an
_end-of-file indicator_ that records whether the end of the file
has been reached

The declaration of FILE in <stdio.hneedn't indicate *how* it records
all that information. For example, it could be declared as

typedef unsigned char[_FILE_BYTES] FILE;

and the library code that uses it could cast the FILE* to, say,
_FILE_STRUCT* to access the information. Most implementations don't
do this; for one thing, the macro definitions for putc and getc are
going to expose some of the inner details anyway.

Since user code only needs to use FILE*, not type FILE itself, an
implementation that declares:

typedef void FILE;

would be perfectly sensible, except that it would violate the
standard's requirement. In my opinion, the standard over-specifies
this, but it's not a huge deal.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 3 '08 #17


Nate Eldredge wrote:
Eric Sosman <Er*********@sun.comwrites:
In C90 you could initialize the unknown member to "zero of
the appropriate type:"

struct foo blah = { 17, { 0 }, 23 };

Some compilers may emit warnings for too few initializers, but
the initialization is valid; if opaque_t is compound, its sub-
elements are initialized to appropriate zeroes. The warnings may
be a nuisance, but they do no actual harm.

Interesting, so the OP was correct after all. I never knew about
"zero of the appropriate type". I assumed that would be wrong if
opaque_t turned out to be a scalar type, or a compound whose first
member was also compound, but apparently not. Those clever language
designers, always one step ahead. :)
{0} initializer is wrong if the first member of opaque_t is an array
Oct 3 '08 #18
Szabolcs Nagy <ns*******@gmail.comwrites:
Nate Eldredge wrote:
>Eric Sosman <Er*********@sun.comwrites:
In C90 you could initialize the unknown member to "zero of
the appropriate type:"

struct foo blah = { 17, { 0 }, 23 };

Some compilers may emit warnings for too few initializers, but
the initialization is valid; if opaque_t is compound, its sub-
elements are initialized to appropriate zeroes. The warnings may
be a nuisance, but they do no actual harm.

Interesting, so the OP was correct after all. I never knew about
"zero of the appropriate type". I assumed that would be wrong if
opaque_t turned out to be a scalar type, or a compound whose first
member was also compound, but apparently not. Those clever language
designers, always one step ahead. :)

{0} initializer is wrong if the first member of opaque_t is an array
Is it really? gcc -ansi -pedantic accepts it.
Oct 3 '08 #19
On Oct 4, 12:41 am, Nate Eldredge <n...@vulcan.lanwrote:
Szabolcs Nagy <nszabo...@gmail.comwrites:
Nate Eldredge wrote:
Eric Sosman <Eric.Sos...@sun.comwrites:
In C90 you could initialize the unknown member to "zero of
the appropriate type:"
struct foo blah = { 17, { 0 }, 23 };
Some compilers may emit warnings for too few initializers, but
the initialization is valid; if opaque_t is compound, its sub-
elements are initialized to appropriate zeroes. The warnings may
be a nuisance, but they do no actual harm.
Interesting, so the OP was correct after all. I never knew about
"zero of the appropriate type". I assumed that would be wrong if
opaque_t turned out to be a scalar type, or a compound whose first
member was also compound, but apparently not. Those clever language
designers, always one step ahead. :)
{0} initializer is wrong if the first member of opaque_t is an array

Is it really? gcc -ansi -pedantic accepts it.

No it isn't, it's correct.

When not all of an object is initialized, the rest is initialized as
if it were 'static'.
Oct 3 '08 #20
vi******@gmail.com writes:
On Oct 4, 12:41 am, Nate Eldredge <n...@vulcan.lanwrote:
>Szabolcs Nagy <nszabo...@gmail.comwrites:
Nate Eldredge wrote:
Eric Sosman <Eric.Sos...@sun.comwrites:
In C90 you could initialize the unknown member to "zero of
the appropriate type:"
struct foo blah = { 17, { 0 }, 23 };
Some compilers may emit warnings for too few initializers, but
the initialization is valid; if opaque_t is compound, its sub-
elements are initialized to appropriate zeroes. The warnings may
be a nuisance, but they do no actual harm.
>Interesting, so the OP was correct after all. I never knew about
"zero of the appropriate type". I assumed that would be wrong if
opaque_t turned out to be a scalar type, or a compound whose first
member was also compound, but apparently not. Those clever language
designers, always one step ahead. :)
{0} initializer is wrong if the first member of opaque_t is an array

Is it really? gcc -ansi -pedantic accepts it.


No it isn't, it's correct.

When not all of an object is initialized, the rest is initialized as
if it were 'static'.
Right, but in this example we have something like

typedef struct {
int arr[5];
double d;
} opaque_t;

struct foo {
int a;
opaque_t op;
int b;
};

struct foo blah = { 17, {0} , 23 };

which on the face of it would appear to initialize blah.op.arr with 0,
which doesn't make sense, instead of { 0 }, which would.

So if I'm understanding correctly, there is a feature in C whereby
{0}, "zero of appropriate type", is valid as an initializer for any
type, which for scalar types initializes to 0, and for aggregate types
initializes each element, recursively, to 0. Can someone provide a
pointer to the standard or another reference which describes this more
fully?

(Incidentally, I'm not sure if I'm correctly using the terms "compound
type" and "aggregate type". I intend them both to refer to a type
which is a structure, union or array.)
Oct 4 '08 #21
Nate Eldredge said:
vi******@gmail.com writes:
>On Oct 4, 12:41 am, Nate Eldredge <n...@vulcan.lanwrote:
>>Szabolcs Nagy <nszabo...@gmail.comwrites:

Nate Eldredge wrote:
Eric Sosman <Eric.Sos...@sun.comwrites:
In C90 you could initialize the unknown member to "zero of
the appropriate type:"

struct foo blah = { 17, { 0 }, 23 };

Some compilers may emit warnings for too few initializers, but
the initialization is valid; if opaque_t is compound, its sub-
elements are initialized to appropriate zeroes. The warnings may
be a nuisance, but they do no actual harm.

Interesting, so the OP was correct after all. I never knew about
"zero of the appropriate type". I assumed that would be wrong if
opaque_t turned out to be a scalar type, or a compound whose first
member was also compound, but apparently not. Those clever language
designers, always one step ahead. :)

{0} initializer is wrong if the first member of opaque_t is an array

Is it really? gcc -ansi -pedantic accepts it.


No it isn't, it's correct.

When not all of an object is initialized, the rest is initialized as
if it were 'static'.

Right, but in this example we have something like

typedef struct {
int arr[5];
double d;
} opaque_t;

struct foo {
int a;
opaque_t op;
int b;
};

struct foo blah = { 17, {0} , 23 };

which on the face of it would appear to initialize blah.op.arr with 0,
which doesn't make sense, instead of { 0 }, which would.
No, you're initialising blah, so the initialiser is used to initialise
blah. Compare and contrast { 17, {{0}, 3.14}, 23 }
So if I'm understanding correctly, there is a feature in C whereby
{0}, "zero of appropriate type", is valid as an initializer for any
type, which for scalar types initializes to 0, and for aggregate types
initializes each element, recursively, to 0. Can someone provide a
pointer to the standard or another reference which describes this more
fully?
It's covered fully in 3.5.7 Initialization (C89) and 6.7.8 Initialization
(C99).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 4 '08 #22
Nate Eldredge <na**@vulcan.lanwrites:
Richard Heathfield <rj*@see.sig.invalidwrites:
[...]
>It's covered fully in 3.5.7 Initialization (C89) and 6.7.8 Initialization
(C99).

Thanks. I bit the bullet and bought a copy of the standard, and now
it makes sense.
[...]

I hope you knew that a post-standard draft, which includes the C99
standard with the three Technical Corrigenda merged into it, is
available at no charge at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>.

I've paid for PDF copies of the C90 and C99 standards myself, but
n1256 is the one I use as a reference most often.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 4 '08 #23
Nate Eldredge wrote:
Szabolcs Nagy <ns*******@gmail.comwrites:
{0} initializer is wrong if the first member of opaque_t is an array

Is it really? gcc -ansi -pedantic accepts it.
i haven't checked the standard (but i remember getting warning for it
with gcc -Wall) now i'm not sure, will check it later
Oct 4 '08 #24
Keith Thompson <ks***@mib.orgwrites:
Nate Eldredge <na**@vulcan.lanwrites:
>Richard Heathfield <rj*@see.sig.invalidwrites:
[...]
>>It's covered fully in 3.5.7 Initialization (C89) and 6.7.8 Initialization
(C99).

Thanks. I bit the bullet and bought a copy of the standard, and now
it makes sense.
[...]

I hope you knew that a post-standard draft, which includes the C99
standard with the three Technical Corrigenda merged into it, is
available at no charge at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>.
Hm. Oh well, I'll consider it a US$30 donation to ANSI, they're a
worthy cause. Might be nice if the FAQ mentioned the draft, however.
The clc-wiki page has a link, I see, but doesn't explain very clearly
what it is.
Oct 4 '08 #25
Szabolcs Nagy wrote, On 04/10/08 06:50:
Nate Eldredge wrote:
>Szabolcs Nagy <ns*******@gmail.comwrites:
>>{0} initializer is wrong if the first member of opaque_t is an array
Is it really? gcc -ansi -pedantic accepts it.

i haven't checked the standard (but i remember getting warning for it
with gcc -Wall) now i'm not sure, will check it later
Compilers are allowed to warn about anything they feel like, so a
compiler warning about something does *not* mean that it is necessarily
invalid, although you should always check the code generating a warning
very carefully and understand *why* the compiler is generating a warning
because often it indicates a real problem.

Conversely, a compiler accepting a program without warning and producing
an executable that works is no guarantee that the program is correct.
The standard does not require warnings for all problems and it is not
practical for a compiler to generate warnings for all possible problems,
and some errors will only trigger a failure under obscure conditions or
if the compiler tries a particularly clever (and valid) optimisation.

In this case, using {0} as an initialiser is valid.
--
Flash Gordon
If spamming me sent it to sm**@spam.causeway.com
If emailing me use my reply-to address
See the comp.lang.c Wiki hosted by me at http://clc-wiki.net/
Oct 4 '08 #26
On 2 Oct, 17:28, Keith Thompson <ks...@mib.orgwrote:

<snip>
There are different kinds of opacity. *Consider type FILE, defined in
<stdio.h>. *That header must completely specify the type
why? user code only needs a pointer
-- but code
that uses it is expected to depend only on the standard functions and
the fact that it's an object type.
<snip>

--
Nick Keighley
Oct 6 '08 #27
On Wed, 1 Oct 2008 16:19:22 -0700 (PDT), vi******@gmail.com wrote:
On Oct 2, 1:28 am, Eric Sosman <Eric.Sos...@sun.comwrote:
...
In C99 you could use a "compound literal:"

struct foo blah = (struct foo){.a = 17, .b = 23};

(Double-check my syntax; I'm typing this hurriedly.)
As already noted, only for auto. Designated-initializer syntax (the
part in the braces) directly as an initializer, not a compound
literal, works in all (C99) cases.
I think you mean

struct foo blah = *(struct foo[]){ { .a = 17, .b = 23 } };
I doubt it. This does not work any better (though not any worse
either) and is unnecessarily cluttered.

- formerly david.thompson1 || achar(64) || worldnet.att.net
Oct 13 '08 #28

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

51 posts views Thread by jacob navia | last post: by
1 post views Thread by Labora | last post: by
26 posts views Thread by Adam Warner | last post: by
6 posts views Thread by William Ahern | last post: by
7 posts views Thread by Eric Laberge | last post: by
3 posts views Thread by Richard Weeks | last post: by
reply views Thread by NPC403 | last post: by
1 post views Thread by UniDue | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.