public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Flexible array member initializers
@ 2014-01-08  5:13 Ian Pilcher
  2014-01-08  8:59 ` Jonathan Wakely
  0 siblings, 1 reply; 10+ messages in thread
From: Ian Pilcher @ 2014-01-08  5:13 UTC (permalink / raw)
  To: gcc-help

I am working on what I hope will be a very simple C configuration file
parsing library/module.  (Because the world obviously needs another
one!)  I define the acceptable options in terms of flexible types:

struct foo_type {
    const char *name;
    int (*parse_fn)(void *dest, const char *text);
    int (*format_fn)(char *buf, size_t buf_size, const void *value);
    void (*free_fn)(void *default_value);
    size_t size;
};

struct foo_opt {
    const char *name;
    const struct foo_type *type;
    unsigned char flags;
    unsigned char def_val[];
};

Note the use of the flexible array member to hold the default value (or
possible a pointer to the default value, depending on the type.)

I'm trying to figure out if there is any way to statically initialize a
struct foo_opt with a default value that is not an array of unsigned
characters.  For example:

struct foo_type foo_int = {
    .name       = "integer",
    .parse_fn   = foo_parse_int,
    .format_fn  = foo_format_int,
    .free_fn    = 0,
    .size       = sizeof(int),
};

struct foo_opt foo_option = {
    .name       = "max_workers",
    .type       = &foo_int,
    .flags      = FOO_OPT_HAS_DEFAULT,
    .def_val    = (unsigned char[])5,
};

My goal is to provide some sort of macro which will make it (reasonably)
simple to provide static initializers for the foo_opt structs -- without
replacing the flexible array member with a void *.

Is there any way to do this?

Thanks!

-- 
========================================================================
Ian Pilcher                                         arequipeno@gmail.com
           Sent from the cloud -- where it's already tomorrow
========================================================================

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Flexible array member initializers
  2014-01-08  5:13 Flexible array member initializers Ian Pilcher
@ 2014-01-08  8:59 ` Jonathan Wakely
  2014-01-08 20:41   ` Ian Pilcher
  0 siblings, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2014-01-08  8:59 UTC (permalink / raw)
  To: Ian Pilcher; +Cc: gcc-help

On Jan 8, 2014 5:13 AM, "Ian Pilcher" wrote:
>
> Note the use of the flexible array member to hold the default value (or
> possible a pointer to the default value, depending on the type.)
>
> I'm trying to figure out if there is any way to statically initialize a
> struct foo_opt with a default value that is not an array of unsigned
> characters.  For example:
>
> struct foo_type foo_int = {
>     .name       = "integer",
>     .parse_fn   = foo_parse_int,
>     .format_fn  = foo_format_int,
>     .free_fn    = 0,
>     .size       = sizeof(int),
> };
>
> struct foo_opt foo_option = {
>     .name       = "max_workers",
>     .type       = &foo_int,
>     .flags      = FOO_OPT_HAS_DEFAULT,
>     .def_val    = (unsigned char[])5,
> };
>
> My goal is to provide some sort of macro which will make it (reasonably)
> simple to provide static initializers for the foo_opt structs -- without
> replacing the flexible array member with a void *.
>
> Is there any way to do this?

No. That's not how flexible array members work.

The member def_value has no storage, so you can't initialize it. To
use it you need to allocate sizeof(struct foo_opt)+sizeof(x) where x
is the value you want def_val to have, and when you access def_val you
will be accessing the extra sizeof(x) bytes after the struct.

I don't see how you can statically initialize a foo_opt when you don't
know sizeof(x).

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Flexible array member initializers
  2014-01-08  8:59 ` Jonathan Wakely
@ 2014-01-08 20:41   ` Ian Pilcher
  2014-01-08 21:00     ` Marc Glisse
                       ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Ian Pilcher @ 2014-01-08 20:41 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-help

On 01/08/2014 03:59 AM, Jonathan Wakely wrote:
> The member def_value has no storage, so you can't initialize it. To
> use it you need to allocate sizeof(struct foo_opt)+sizeof(x) where x
> is the value you want def_val to have, and when you access def_val you
> will be accessing the extra sizeof(x) bytes after the struct.
>
> I don't see how you can statically initialize a foo_opt when you don't
> know sizeof(x).
>

Here's a very simplified example for the specific case of a 16-bit short
on a little-endian system:

#define SHORT_BYTES(s)	{ ((s) & 0xff), (((s) >> 8) & 0xff) }

struct foo {
     size_t value_size;
     unsigned char value[];
};

static struct foo foo_short = {
     .value_size = sizeof(short),
     .value      = SHORT_BYTES(513),
};

Ideally I could create some sort of generic macro that "casts" (using
the term very loosely) any static initializer to an array of unsigned
char that contains its binary representation.  Sadly, I don't think
that's actually possible.

I don't supposed that gcc provides any facility that will allow the
pre-processor to determine endianness and/or type sizes?

-- 
========================================================================
Ian Pilcher                                         arequipeno@gmail.com
"If you're going to shift my paradigm ... at least buy me dinner first."
========================================================================

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Flexible array member initializers
  2014-01-08 20:41   ` Ian Pilcher
@ 2014-01-08 21:00     ` Marc Glisse
  2014-01-08 21:46       ` Ian Pilcher
  2014-01-08 21:43     ` Jonathan Wakely
  2014-01-08 23:23     ` Ángel González
  2 siblings, 1 reply; 10+ messages in thread
From: Marc Glisse @ 2014-01-08 21:00 UTC (permalink / raw)
  To: Ian Pilcher; +Cc: gcc-help

On Wed, 8 Jan 2014, Ian Pilcher wrote:

> I don't supposed that gcc provides any facility that will allow the
> pre-processor to determine endianness and/or type sizes?

With an empty file empty.c, try: gcc -dM -E empty.c
and see if there is anything you like in what it prints.

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Flexible array member initializers
  2014-01-08 20:41   ` Ian Pilcher
  2014-01-08 21:00     ` Marc Glisse
@ 2014-01-08 21:43     ` Jonathan Wakely
  2014-01-08 21:49       ` Ian Pilcher
  2014-01-08 23:23     ` Ángel González
  2 siblings, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2014-01-08 21:43 UTC (permalink / raw)
  To: Ian Pilcher; +Cc: gcc-help

On 8 January 2014 20:41, Ian Pilcher wrote:
> On 01/08/2014 03:59 AM, Jonathan Wakely wrote:
>>
>> The member def_value has no storage, so you can't initialize it. To
>> use it you need to allocate sizeof(struct foo_opt)+sizeof(x) where x
>> is the value you want def_val to have, and when you access def_val you
>> will be accessing the extra sizeof(x) bytes after the struct.
>>
>> I don't see how you can statically initialize a foo_opt when you don't
>> know sizeof(x).
>>
>
> Here's a very simplified example for the specific case of a 16-bit short
> on a little-endian system:
>
> #define SHORT_BYTES(s)  { ((s) & 0xff), (((s) >> 8) & 0xff) }
>
> struct foo {
>     size_t value_size;
>     unsigned char value[];
> };
>
> static struct foo foo_short = {
>     .value_size = sizeof(short),
>     .value      = SHORT_BYTES(513),
> };

Where do you think those two bytes are meant to be stored?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Flexible array member initializers
  2014-01-08 21:00     ` Marc Glisse
@ 2014-01-08 21:46       ` Ian Pilcher
  0 siblings, 0 replies; 10+ messages in thread
From: Ian Pilcher @ 2014-01-08 21:46 UTC (permalink / raw)
  To: gcc-help

On 01/08/2014 04:00 PM, Marc Glisse wrote:
> With an empty file empty.c, try: gcc -dM -E empty.c
> and see if there is anything you like in what it prints.

Cool!  Looks like I once more get to escape learning autoconf.  ;-)

But ... this is going to be a non-starter for anything but integer
types.  There's simply no way to do equivalent "bit twiddling" with
floating point or pointer types in a static initializer.

I think it's time to pull my head out of the rat hole and accept that
the odd extra void * isn't so bad ...

Thanks!

-- 
========================================================================
Ian Pilcher                                         arequipeno@gmail.com
"If you're going to shift my paradigm ... at least buy me dinner first."
========================================================================

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Flexible array member initializers
  2014-01-08 21:43     ` Jonathan Wakely
@ 2014-01-08 21:49       ` Ian Pilcher
  2014-01-08 22:21         ` Jonathan Wakely
  0 siblings, 1 reply; 10+ messages in thread
From: Ian Pilcher @ 2014-01-08 21:49 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-help

On 01/08/2014 04:42 PM, Jonathan Wakely wrote:
>> #define SHORT_BYTES(s)  { ((s) & 0xff), (((s) >> 8) & 0xff) }
>>
>> struct foo {
>>      size_t value_size;
>>      unsigned char value[];
>> };
>>
>> static struct foo foo_short = {
>>      .value_size = sizeof(short),
>>      .value      = SHORT_BYTES(513),
>> };
>
> Where do you think those two bytes are meant to be stored?
>

Maybe I don't understand your question, but the two bytes that make up
the short get stored in the "value" element (as an array of 2 unsigned
characters).

That said, since I've realized that this simply isn't going to work for
anything but integer types, I'm going to give up on the flexible array
member for this particular use.

-- 
========================================================================
Ian Pilcher                                         arequipeno@gmail.com
"If you're going to shift my paradigm ... at least buy me dinner first."
========================================================================

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Flexible array member initializers
  2014-01-08 21:49       ` Ian Pilcher
@ 2014-01-08 22:21         ` Jonathan Wakely
  0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2014-01-08 22:21 UTC (permalink / raw)
  To: Ian Pilcher; +Cc: gcc-help

On 8 January 2014 21:48, Ian Pilcher wrote:
> On 01/08/2014 04:42 PM, Jonathan Wakely wrote:
>>>
>>> #define SHORT_BYTES(s)  { ((s) & 0xff), (((s) >> 8) & 0xff) }
>>>
>>> struct foo {
>>>      size_t value_size;
>>>      unsigned char value[];
>>> };
>>>
>>> static struct foo foo_short = {
>>>      .value_size = sizeof(short),
>>>      .value      = SHORT_BYTES(513),
>>> };
>>
>>
>> Where do you think those two bytes are meant to be stored?
>>
>
> Maybe I don't understand your question, but the two bytes that make up
> the short get stored in the "value" element (as an array of 2 unsigned
> characters).

The point of my question is that the 'value' member is an incomplete
type, it does not have any storage, so there is nowhere to store those
two bytes.

But I didn't realise GCC has a non-standard extension that does allow
what you're doing, automatically allocating space after the struct:
http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Flexible array member initializers
  2014-01-08 20:41   ` Ian Pilcher
  2014-01-08 21:00     ` Marc Glisse
  2014-01-08 21:43     ` Jonathan Wakely
@ 2014-01-08 23:23     ` Ángel González
  2014-01-11  2:03       ` Ian Pilcher
  2 siblings, 1 reply; 10+ messages in thread
From: Ángel González @ 2014-01-08 23:23 UTC (permalink / raw)
  To: Ian Pilcher; +Cc: gcc-help

On 08/01/14 21:41, Ian Pilcher wrote:
> Ideally I could create some sort of generic macro that "casts" (using
> the term very loosely) any static initializer to an array of unsigned
> char that contains its binary representation.  Sadly, I don't think
> that's actually possible.
I think you want to use an union, not a flexible array (yes, you will
overallocate for some types, but should be saner).

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Flexible array member initializers
  2014-01-08 23:23     ` Ángel González
@ 2014-01-11  2:03       ` Ian Pilcher
  0 siblings, 0 replies; 10+ messages in thread
From: Ian Pilcher @ 2014-01-11  2:03 UTC (permalink / raw)
  To: gcc-help

On 01/08/2014 06:23 PM, Ángel González wrote:
> I think you want to use an union, not a flexible array (yes, you will
> overallocate for some types, but should be saner).

The problem with using a union is that it doesn't allow for storage
of *any* type -- a structure for example.

As I said in another post, I've realized that this simply isn't going
to work.  I'll just use a void pointer.

Thanks all!


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-01-11  2:03 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-08  5:13 Flexible array member initializers Ian Pilcher
2014-01-08  8:59 ` Jonathan Wakely
2014-01-08 20:41   ` Ian Pilcher
2014-01-08 21:00     ` Marc Glisse
2014-01-08 21:46       ` Ian Pilcher
2014-01-08 21:43     ` Jonathan Wakely
2014-01-08 21:49       ` Ian Pilcher
2014-01-08 22:21         ` Jonathan Wakely
2014-01-08 23:23     ` Ángel González
2014-01-11  2:03       ` Ian Pilcher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).