Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #162195 > unrolled thread

Padding between char array/VLA in struct?

Started byIan Pilcher <arequipeno@gmail.com>
First post2021-08-02 12:48 -0500
Last post2021-08-04 10:11 -0700
Articles 9 on this page of 29 — 10 participants

Back to article view | Back to comp.lang.c


Contents

  Padding between char array/VLA in struct? Ian Pilcher <arequipeno@gmail.com> - 2021-08-02 12:48 -0500
    Re: Padding between char array/VLA in struct? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-08-02 14:07 -0400
      Re: Padding between char array/VLA in struct? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-02 11:25 -0700
        Re: Padding between char array/VLA in struct? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-08-02 19:21 -0400
    Re: Padding between char array/VLA in struct? Bart <bc@freeuk.com> - 2021-08-02 19:11 +0100
      Re: Padding between char array/VLA in struct? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-02 11:27 -0700
        Re: Padding between char array/VLA in struct? Bart <bc@freeuk.com> - 2021-08-02 20:43 +0100
          Re: Padding between char array/VLA in struct? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-08-02 13:11 -0700
            Re: Padding between char array/VLA in struct? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-08-02 13:18 -0700
            Re: Padding between char array/VLA in struct? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-02 13:31 -0700
              Re: Padding between char array/VLA in struct? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-08-02 19:50 -0700
                Re: Padding between char array/VLA in struct? David Brown <david.brown@hesbynett.no> - 2021-08-04 14:01 +0200
          Re: Padding between char array/VLA in struct? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-02 13:19 -0700
          Re: Padding between char array/VLA in struct? BGB <cr88192@gmail.com> - 2021-08-03 10:40 -0500
            Re: Padding between char array/VLA in struct? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-08-03 09:10 -0700
              Re: Padding between char array/VLA in struct? BGB <cr88192@gmail.com> - 2021-08-03 12:52 -0500
                Re: Padding between char array/VLA in struct? BGB <cr88192@gmail.com> - 2021-08-04 12:05 -0500
    Re: Padding between char array/VLA in struct? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-02 11:12 -0700
      Re: Padding between char array/VLA in struct? Bart <bc@freeuk.com> - 2021-08-02 19:23 +0100
        Re: Padding between char array/VLA in struct? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-02 13:15 -0700
    Re: Padding between char array/VLA in struct? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-08-02 11:32 -0700
    Re: Padding between char array/VLA in struct? Ian Pilcher <arequipeno@gmail.com> - 2021-08-02 13:59 -0500
      Re: Padding between char array/VLA in struct? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-08-02 12:47 -0700
        Re: Padding between char array/VLA in struct? Ian Pilcher <arequipeno@gmail.com> - 2021-08-02 15:27 -0500
          Re: Padding between char array/VLA in struct? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-02 13:36 -0700
          Re: Padding between char array/VLA in struct? antispam@math.uni.wroc.pl - 2021-08-02 21:52 +0000
      Re: Padding between char array/VLA in struct? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-02 13:22 -0700
        Re: Padding between char array/VLA in struct? Manfred <noname@add.invalid> - 2021-08-04 17:01 +0200
          Re: Padding between char array/VLA in struct? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-04 10:11 -0700

Page 2 of 2 — ← Prev page 1 [2]


#162202

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2021-08-02 11:32 -0700
Message-ID<se9dnc$8a3$1@dont-email.me>
In reply to#162195
On 8/2/2021 10:48 AM, Ian Pilcher wrote:
> Given the following:
> 
>    struct foo {
>        /* other members */
>        char prefix[PREFIX_SIZE];
>        char name[];
>    };
> 
> Is there any circumstance in which the compiler is permitted to insert
> padding between the 'prefix' and 'name' members?
> 
> I'm 99% sure than the answer is no, but I've been unable to track down
> the actual rules anywhere.
> 

As far as the formal rules of the language are considered, the compiler 
is _always_ permitted to insert padding between struct members (and 
after the last member) for whatever reason it pleases. Extra padding can 
always be added anywhere, except before the first member of the struct.

So, the answer is "yes".

Also, it is not clear why you mention VLA in the title of your question. 
The language does not allow VLA as a struct members. The last member of 
your struct is called "flexible array member". This is not VLA and has 
nothing to do with VLA.

-- 
Best regards,
Andrey Tarasevich

[toc] | [prev] | [next] | [standalone]


#162203

FromIan Pilcher <arequipeno@gmail.com>
Date2021-08-02 13:59 -0500
Message-ID<se9fa1$ikv$1@dont-email.me>
In reply to#162195
On 8/2/21 12:48 PM, Ian Pilcher wrote:
> Given the following:
> 
>    struct foo {
>        /* other members */
>        char prefix[PREFIX_SIZE];
>        char name[];
>    };

As has been pointed out, the 'name' member is a flexible array member,
not a variable length array.  I apologize for the mistake.

Also, PREFIX_SIZE is intended to represent a macro that expands to a
positive(!) integer constant expression.

The consensus seems to be that no one can think of a good reason that a
compiler would insert padding between the 'prefix' and 'name' members,
but there's nothing in any of the language standards that would forbid
it from doing so.  That would certainly explain my failure to find any
such rule.

(_Static_assert here I come!)

Thanks!

-- 
========================================================================
Ian Pilcher                                         arequipeno@gmail.com
-------- "I grew up before Mark Zuckerberg invented friendship" --------
========================================================================

[toc] | [prev] | [next] | [standalone]


#162205

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-08-02 12:47 -0700
Message-ID<867dh34oia.fsf@linuxsc.com>
In reply to#162203
Ian Pilcher <arequipeno@gmail.com> writes:

> On 8/2/21 12:48 PM, Ian Pilcher wrote:
>
>> Given the following:
>>
>>   struct foo {
>>   /* other members */
>>   char prefix[PREFIX_SIZE];
>>   char name[];
>>   };
>
> As has been pointed out, the 'name' member is a flexible array member,
> not a variable length array.  I apologize for the mistake.
>
> Also, PREFIX_SIZE is intended to represent a macro that expands to a
> positive(!) integer constant expression.
>
> The consensus seems to be that no one can think of a good reason that a
> compiler would insert padding between the 'prefix' and 'name' members,
> but there's nothing in any of the language standards that would forbid
> it from doing so.  That would certainly explain my failure to find any
> such rule.
>
> (_Static_assert here I come!)

I am curious to know why you care.  Would having a guarantee that
there is no padding affect what code you would write?  If it
would then there is a good chance that guarantee-depending code
has undefined behavior somewhere.

[toc] | [prev] | [next] | [standalone]


#162211

FromIan Pilcher <arequipeno@gmail.com>
Date2021-08-02 15:27 -0500
Message-ID<se9kev$ndj$1@dont-email.me>
In reply to#162205
On 8/2/21 2:47 PM, Tim Rentsch wrote:
> I am curious to know why you care.  Would having a guarantee that
> there is no padding affect what code you would write?  If it
> would then there is a good chance that guarantee-depending code
> has undefined behavior somewhere.

It's just a convenient way to refer to either the "full" name (including
the prefix) or the unique part of the name.  For example, I've got a
bunch of struct foo's, each of which has a name that starts with "FOO:",
and most of the time I don't care about the prefix.

   #define FOO_PREFIX "FOO:"

   static const char foo_prefix[sizeof FOO_PREFIX - 1] = FOO_PREFIX;

   struct foo {
       /* other members */
       char prefix[sizeof foo_prefix];
       char name[];
   }

   struct foo *alloc_foo(char *name)
   {
       struct foo *f;

       f = malloc(sizeof *f + strlen(name) + 1);

       // Or do something clever with sprintf()
       memcpy(&f->prefix, foo_prefix, sizeof foo_prefix);
       memcpy(&f->name, name, strlen(name) + 1);

       return f;
   }

For a given struct foo *f, I can access the full name as f->prefix, and
I can access the unique part as f->name.

-- 
========================================================================
Ian Pilcher                                         arequipeno@gmail.com
-------- "I grew up before Mark Zuckerberg invented friendship" --------
========================================================================

[toc] | [prev] | [next] | [standalone]


#162213

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-08-02 13:36 -0700
Message-ID<87k0l38tzd.fsf@nosuchdomain.example.com>
In reply to#162211
Ian Pilcher <arequipeno@gmail.com> writes:
> On 8/2/21 2:47 PM, Tim Rentsch wrote:
>> I am curious to know why you care.  Would having a guarantee that
>> there is no padding affect what code you would write?  If it
>> would then there is a good chance that guarantee-depending code
>> has undefined behavior somewhere.
>
> It's just a convenient way to refer to either the "full" name (including
> the prefix) or the unique part of the name.  For example, I've got a
> bunch of struct foo's, each of which has a name that starts with "FOO:",
> and most of the time I don't care about the prefix.
>
>   #define FOO_PREFIX "FOO:"
>
>   static const char foo_prefix[sizeof FOO_PREFIX - 1] = FOO_PREFIX;
>
>   struct foo {
>       /* other members */
>       char prefix[sizeof foo_prefix];
>       char name[];
>   }
>
>   struct foo *alloc_foo(char *name)
>   {
>       struct foo *f;
>
>       f = malloc(sizeof *f + strlen(name) + 1);
>
>       // Or do something clever with sprintf()
>       memcpy(&f->prefix, foo_prefix, sizeof foo_prefix);
>       memcpy(&f->name, name, strlen(name) + 1);
>
>       return f;
>   }
>
> For a given struct foo *f, I can access the full name as f->prefix, and
> I can access the unique part as f->name.

Suggestion: Combine `prefix` and `name` into a single array of char, and
use `name+offset` to refer to the portion of the string following the
prefix.  Arrays are guaranteed to be contiguous.

If f->name contains a string whose length is at least 4, then f-name and
f->name+4 are both valid pointers to strings.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#162214

Fromantispam@math.uni.wroc.pl
Date2021-08-02 21:52 +0000
Message-ID<se9peg$5o4$1@z-news.wcss.wroc.pl>
In reply to#162211
Ian Pilcher <arequipeno@gmail.com> wrote:
> On 8/2/21 2:47 PM, Tim Rentsch wrote:
> > I am curious to know why you care.  Would having a guarantee that
> > there is no padding affect what code you would write?  If it
> > would then there is a good chance that guarantee-depending code
> > has undefined behavior somewhere.
> 
> It's just a convenient way to refer to either the "full" name (including
> the prefix) or the unique part of the name.  For example, I've got a
> bunch of struct foo's, each of which has a name that starts with "FOO:",
> and most of the time I don't care about the prefix.
> 
>   #define FOO_PREFIX "FOO:"
> 
>   static const char foo_prefix[sizeof FOO_PREFIX - 1] = FOO_PREFIX;
> 
>   struct foo {
>       /* other members */
>       char prefix[sizeof foo_prefix];
>       char name[];
>   }
> 
>   struct foo *alloc_foo(char *name)
>   {
>       struct foo *f;
> 
>       f = malloc(sizeof *f + strlen(name) + 1);
> 
>       // Or do something clever with sprintf()
>       memcpy(&f->prefix, foo_prefix, sizeof foo_prefix);
>       memcpy(&f->name, name, strlen(name) + 1);
> 
>       return f;
>   }
> 
> For a given struct foo *f, I can access the full name as f->prefix,

No, you can not.  Going above prefix length is undefined behaviour.
I know no "production" compiler that would detect it, but there
are various debugging aids and some should catch it.

> and
> I can access the unique part as f->name.

-- 
                              Waldek Hebisch

[toc] | [prev] | [next] | [standalone]


#162210

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-08-02 13:22 -0700
Message-ID<87sfzr8umf.fsf@nosuchdomain.example.com>
In reply to#162203
Ian Pilcher <arequipeno@gmail.com> writes:
> On 8/2/21 12:48 PM, Ian Pilcher wrote:
>> Given the following:
>>    struct foo {
>>        /* other members */
>>        char prefix[PREFIX_SIZE];
>>        char name[];
>>    };
>
> As has been pointed out, the 'name' member is a flexible array member,
> not a variable length array.  I apologize for the mistake.
>
> Also, PREFIX_SIZE is intended to represent a macro that expands to a
> positive(!) integer constant expression.
>
> The consensus seems to be that no one can think of a good reason that a
> compiler would insert padding between the 'prefix' and 'name' members,
> but there's nothing in any of the language standards that would forbid
> it from doing so.  That would certainly explain my failure to find any
> such rule.
>
> (_Static_assert here I come!)

The ABI for whatever target platform you're interested in might have
something to say about it.

(I can imagine that some compiler might find it convenient to give the
name[] member an alignment stricter than 1 byte.)

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#162227

FromManfred <noname@add.invalid>
Date2021-08-04 17:01 +0200
Message-ID<seea3q$7a6$1@gioia.aioe.org>
In reply to#162210
On 8/2/2021 10:22 PM, Keith Thompson wrote:
> Ian Pilcher <arequipeno@gmail.com> writes:
>> On 8/2/21 12:48 PM, Ian Pilcher wrote:
>>> Given the following:
>>>     struct foo {
>>>         /* other members */
>>>         char prefix[PREFIX_SIZE];
>>>         char name[];
>>>     };
>>
>> As has been pointed out, the 'name' member is a flexible array member,
>> not a variable length array.  I apologize for the mistake.
>>
>> Also, PREFIX_SIZE is intended to represent a macro that expands to a
>> positive(!) integer constant expression.
>>
>> The consensus seems to be that no one can think of a good reason that a
>> compiler would insert padding between the 'prefix' and 'name' members,
>> but there's nothing in any of the language standards that would forbid
>> it from doing so.  That would certainly explain my failure to find any
>> such rule.
>>
>> (_Static_assert here I come!)
> 
> The ABI for whatever target platform you're interested in might have
> something to say about it.

It may be worth pointing out that ABIs set requirements for exported 
interfaces - they don't pose restrictions to compilers for accesses to 
local data and functions.

> 
> (I can imagine that some compiler might find it convenient to give the
> name[] member an alignment stricter than 1 byte.)
> 

[toc] | [prev] | [next] | [standalone]


#162233

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-08-04 10:11 -0700
Message-ID<87fsvp879i.fsf@nosuchdomain.example.com>
In reply to#162227
Manfred <noname@add.invalid> writes:
> On 8/2/2021 10:22 PM, Keith Thompson wrote:
>> Ian Pilcher <arequipeno@gmail.com> writes:
>>> On 8/2/21 12:48 PM, Ian Pilcher wrote:
>>>> Given the following:
>>>>     struct foo {
>>>>         /* other members */
>>>>         char prefix[PREFIX_SIZE];
>>>>         char name[];
>>>>     };
>>>
>>> As has been pointed out, the 'name' member is a flexible array member,
>>> not a variable length array.  I apologize for the mistake.
>>>
>>> Also, PREFIX_SIZE is intended to represent a macro that expands to a
>>> positive(!) integer constant expression.
>>>
>>> The consensus seems to be that no one can think of a good reason that a
>>> compiler would insert padding between the 'prefix' and 'name' members,
>>> but there's nothing in any of the language standards that would forbid
>>> it from doing so.  That would certainly explain my failure to find any
>>> such rule.
>>>
>>> (_Static_assert here I come!)
>> The ABI for whatever target platform you're interested in might have
>> something to say about it.
>
> It may be worth pointing out that ABIs set requirements for exported
> interfaces - they don't pose restrictions to compilers for accesses to 
> local data and functions.

Sure, but it would be bizarre to use the ABI-imposed layout for struct foo
if it's exported, but a different layout if it isn't.

>> (I can imagine that some compiler might find it convenient to give
>> the
>> name[] member an alignment stricter than 1 byte.)

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.c


csiph-web