Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > How to be sure a structure field is aligned

Reply
Thread Tools

How to be sure a structure field is aligned

 
 
pozzugno@gmail.com
Guest
Posts: n/a
 
      04-19-2012
I have a structure defined as:

struct MyStruct {
<some fields of different types>
unsigned char buffer[MAX_BUFLEN];
};

The array buffer[] can store different types of variables: int, unsigned int, long, unsigned long, null-terminated strings (of course, MAX_BUFLEN >=sizeof(long)).

Am I allowed to use a cast to long or int, as in the following instructions?
struct MyStruct s;
(long *)s.buffer = -100000L;
(unsigned long *)s.buffer = +100000UL;
(int *)s.buffer = -100;
(unsigned int *)s.buffer = +100U;
long l = *(long *)s.buffer;
unsigned long ul = *(unsigned long)s.buffer;
int i = *(int *)s.buffer;
unsigned int ui = *(unsigned int *)s.buffer;

I think this could work on some platforms, but is not fully portable (mostly on 16- and 32-bits). It would work only if buffer[] field is correctly aligned in the structure, but it's not guaranteed (it may depends from the previous fields in the structure).

I think there are two solutions.
Avoiding to use cast and use memcpy (but I don't like it):
long l = -100000L;
unsigned long ul = 100000UL;
int i = -100;
unsigned int ui = +100;
memcpy(s.buffer, &l, sizeof(l));
memcpy(s.buffer, &ul, sizeof(ul));
memcpy(s.buffer, &i, sizeof(i));
memcpy(s.buffer, &ui, sizeof(ui));
memcpy(&l, s.buffer, sizeof(l));
memcpy(&ul, s.buffer, sizeof(ul));
memcpy(&i, s.buffer, sizeof(i));
memcpy(&ui, s.buffer, sizeof(ui));

Moving the buffer[] field at the top of the structure, so it is aligned forsure and I can use casting.

Another solution could be to define MyStruct as:

struct MyStruct {
<some fields of different types>
struct {
unsigned char buffer[MAX_BUFLEN];
} buf_aligned;
};

Are thre other solutions?

PS: I'm working on an embedded platform, so I don't have dynamic allocationmalloc/free (otherwise buffer could had be defined as a pointer and the memory space could had be allocated dynamically with malloc that surely returns aligned pointers).

 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      04-19-2012
On 04/19/12 07:45 PM, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> I have a structure defined as:
>
> struct MyStruct {
> <some fields of different types>
> unsigned char buffer[MAX_BUFLEN];
> };
>
> The array buffer[] can store different types of variables: int, unsigned int, long, unsigned long, null-terminated strings (of course, MAX_BUFLEN>= sizeof(long)).


One simple (cast free) solution would be to use an enum.

--
Ian Collins
 
Reply With Quote
 
 
 
 
pozzugno@gmail.com
Guest
Posts: n/a
 
      04-19-2012
Il giorno giovedý 19 aprile 2012 10:02:56 UTC+2, Ian Collins ha scritto:
> On 04/19/12 07:45 PM, (E-Mail Removed) wrote:
> > I have a structure defined as:
> >
> > struct MyStruct {
> > <some fields of different types>
> > unsigned char buffer[MAX_BUFLEN];
> > };
> >
> > The array buffer[] can store different types of variables: int, unsigned int, long, unsigned long, null-terminated strings (of course, MAX_BUFLEN>= sizeof(long)).

>
> One simple (cast free) solution would be to use an enum.


I'm sorry, could you detail? If I add an enum field in the structure (I imagine to specify the type of variable stored in the buffer), I will continuehaving the alignment problem on buffer.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      04-19-2012
On 04/19/12 09:01 PM, (E-Mail Removed) wrote:
> Il giorno giovedý 19 aprile 2012 10:02:56 UTC+2, Ian Collins ha scritto:
>> On 04/19/12 07:45 PM, (E-Mail Removed) wrote:
>>> I have a structure defined as:
>>>
>>> struct MyStruct {
>>> <some fields of different types>
>>> unsigned char buffer[MAX_BUFLEN];
>>> };
>>>
>>> The array buffer[] can store different types of variables: int, unsigned int, long, unsigned long, null-terminated strings (of course, MAX_BUFLEN>= sizeof(long)).

>>
>> One simple (cast free) solution would be to use an enum.

>
> I'm sorry, could you detail? If I add an enum field in the structure (I imagine to specify the type of variable stored in the buffer), I will continue having the alignment problem on buffer.


No, the enum ember will be correctly aligned for all of its types.

--
Ian Collins
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      04-19-2012
On 04/19/2012 06:30 AM, Ian Collins wrote:
> On 04/19/12 09:01 PM, (E-Mail Removed) wrote:
>> Il giorno gioved´┐Ż 19 aprile 2012 10:02:56 UTC+2, Ian Collins ha scritto:
>>> On 04/19/12 07:45 PM, (E-Mail Removed) wrote:
>>>> I have a structure defined as:
>>>>
>>>> struct MyStruct {
>>>> <some fields of different types>
>>>> unsigned char buffer[MAX_BUFLEN];
>>>> };
>>>>
>>>> The array buffer[] can store different types of variables: int, unsigned int, long, unsigned long, null-terminated strings (of course, MAX_BUFLEN>= sizeof(long)).
>>>
>>> One simple (cast free) solution would be to use an enum.

>>
>> I'm sorry, could you detail? If I add an enum field in the structure (I imagine to specify the type of variable stored in the buffer), I will continue having the alignment problem on buffer.

>
> No, the enum ember will be correctly aligned for all of its types.


Did you mean "union" rather than "enum"?
--
James Kuyper
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      04-19-2012
On 04/19/12 10:35 PM, James Kuyper wrote:
> On 04/19/2012 06:30 AM, Ian Collins wrote:
>> On 04/19/12 09:01 PM, (E-Mail Removed) wrote:
>>> Il giorno gioved´┐Ż 19 aprile 2012 10:02:56 UTC+2, Ian Collins ha scritto:
>>>> On 04/19/12 07:45 PM, (E-Mail Removed) wrote:
>>>>> I have a structure defined as:
>>>>>
>>>>> struct MyStruct {
>>>>> <some fields of different types>
>>>>> unsigned char buffer[MAX_BUFLEN];
>>>>> };
>>>>>
>>>>> The array buffer[] can store different types of variables: int, unsigned int, long, unsigned long, null-terminated strings (of course, MAX_BUFLEN>= sizeof(long)).
>>>>
>>>> One simple (cast free) solution would be to use an enum.
>>>
>>> I'm sorry, could you detail? If I add an enum field in the structure (I imagine to specify the type of variable stored in the buffer), I will continue having the alignment problem on buffer.

>>
>> No, the enum ember will be correctly aligned for all of its types.

>
> Did you mean "union" rather than "enum"?


Oops, yes. It's been a long day...

--
Ian Collins
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      04-19-2012
On 04/19/2012 03:45 AM, (E-Mail Removed) wrote:
> I have a structure defined as:
>
> struct MyStruct {
> <some fields of different types>
> unsigned char buffer[MAX_BUFLEN];
> };
>
> The array buffer[] can store different types of variables: int,
> unsigned int, long, unsigned long, null-terminated strings (of
> course, MAX_BUFLEN >= sizeof(long)).
>
> Am I allowed to use a cast to long or int, as in the following
> instructions?
> struct MyStruct s;
> (long *)s.buffer = -100000L;
> (unsigned long *)s.buffer = +100000UL;
> (int *)s.buffer = -100;
> (unsigned int *)s.buffer = +100U;
> long l = *(long *)s.buffer;
> unsigned long ul = *(unsigned long)s.buffer;
> int i = *(int *)s.buffer;
> unsigned int ui = *(unsigned int *)s.buffer;
>
> I think this could work on some platforms, but is not fully portable
> (mostly on 16- and 32-bits). It would work only if buffer[] field is
> correctly aligned in the structure, but it's not guaranteed (it may
> depends from the previous fields in the structure).
>
> I think there are two solutions.
> Avoiding to use cast and use memcpy (but I don't like it):
> long l = -100000L;
> unsigned long ul = 100000UL;
> int i = -100;
> unsigned int ui = +100;
> memcpy(s.buffer, &l, sizeof(l));
> memcpy(s.buffer, &ul, sizeof(ul));
> memcpy(s.buffer, &i, sizeof(i));
> memcpy(s.buffer, &ui, sizeof(ui));
> memcpy(&l, s.buffer, sizeof(l));
> memcpy(&ul, s.buffer, sizeof(ul));
> memcpy(&i, s.buffer, sizeof(i));
> memcpy(&ui, s.buffer, sizeof(ui));


That works, but is not the best solution.

> Moving the buffer[] field at the top of the structure, so it is
> aligned for sure and I can use casting.


The structure will have an alignment requirement at least as great as
the most strictly aligned type of any member. If the other members of
the structure include an 'int', then putting buffer at the beginning is
sufficient to ensure that it's correctly aligned for conversion to
'int'. If the other members include a long, then putting buffer at the
beginning will be sufficient to ensure it's correctly aligned for a
long. Otherwise, there's no guarantee. Even if those cases apply, it's a
bad idea to rely upon something like that: your code using buffer could
break if you remove or change the types of other members of the struct.

> Another solution could be to define MyStruct as:
>
> struct MyStruct {
> <some fields of different types>
> struct {
> unsigned char buffer[MAX_BUFLEN];
> } buf_aligned;
> };


The fact that you think this makes a difference suggests that you
believe structs always have universal alignment. That may be true on
many systems, but there's no such requirement.

> Are thre other solutions?


Yes - what you're trying to do is precisely what unions were invented to
handle. You should define a discriminated union structure:

struct MyStruct {
enum {UNKNOWN, INT, UINT, LONG, ULONG} member_type;
union {
int i;
unsigned int ui;
long l;
unsigned long ul;
} member;
};

The fields member.i, member.ui, member.l, and member.ul are all
guaranteed to be correctly aligned, and are all stored in overlapping
memory locations. Therefore, only one member of the union can be in use
at any given time. Set member_type to indicate which one that is -
that's the feature that makes this a "discriminated" union. The names
I've used for the enumeration constants aren't very good; they should be
longer, to avoid conflict with other identifiers, but I hope you get the
idea. If you're using the same constants in many other contexts, you
should move the definition of the enumeration outside the definition of
the struct.

--
James Kuyper
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      04-19-2012
On 04/19/2012 06:42 AM, Ian Collins wrote:
> On 04/19/12 10:35 PM, James Kuyper wrote:
>> On 04/19/2012 06:30 AM, Ian Collins wrote:

....
>>> No, the enum ember will be correctly aligned for all of its types.

>>
>> Did you mean "union" rather than "enum"?

>
> Oops, yes. It's been a long day...


You're in zone +12? Get some sleep. I just woke up.
--
James Kuyper
 
Reply With Quote
 
pozzugno@gmail.com
Guest
Posts: n/a
 
      04-19-2012
Il giorno giovedý 19 aprile 2012 13:02:33 UTC+2, James Kuyper ha scritto:
> On 04/19/2012 03:45 AM, (E-Mail Removed) wrote:


[...]
> > Moving the buffer[] field at the top of the structure, so it is
> > aligned for sure and I can use casting.

>
> The structure will have an alignment requirement at least as great as
> the most strictly aligned type of any member. If the other members of
> the structure include an 'int', then putting buffer at the beginning is
> sufficient to ensure that it's correctly aligned for conversion to
> 'int'. If the other members include a long, then putting buffer at the
> beginning will be sufficient to ensure it's correctly aligned for a
> long. Otherwise, there's no guarantee.


I thought the beginning of a struct (its first field) was perfectly aligned
for every primitive type (int, long int, float...). The same as pointer
returned from malloc().

> Even if those cases apply, it's a
> bad idea to rely upon something like that: your code using buffer could
> break if you remove or change the types of other members of the struct.


Sure.


> > Another solution could be to define MyStruct as:
> >
> > struct MyStruct {
> > <some fields of different types>
> > struct {
> > unsigned char buffer[MAX_BUFLEN];
> > } buf_aligned;
> > };

>
> The fact that you think this makes a difference suggests that you
> believe structs always have universal alignment. That may be true on
> many systems, but there's no such requirement.


Yes, I thought so. I was wrong


> > Are thre other solutions?

>
> Yes - what you're trying to do is precisely what unions were invented to
> handle.

[...]

Yes, this is THE SOLUTION! Thank you very much.
 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      04-19-2012
On Thu, 19 Apr 2012 07:53:20 -0700 (PDT), (E-Mail Removed) wrote:

>Il giorno giovedý 19 aprile 2012 13:02:33 UTC+2, James Kuyper ha scritto:
>> On 04/19/2012 03:45 AM, (E-Mail Removed) wrote:

>
>[...]
>> > Moving the buffer[] field at the top of the structure, so it is
>> > aligned for sure and I can use casting.

>>
>> The structure will have an alignment requirement at least as great as
>> the most strictly aligned type of any member. If the other members of
>> the structure include an 'int', then putting buffer at the beginning is
>> sufficient to ensure that it's correctly aligned for conversion to
>> 'int'. If the other members include a long, then putting buffer at the
>> beginning will be sufficient to ensure it's correctly aligned for a
>> long. Otherwise, there's no guarantee.

>
>I thought the beginning of a struct (its first field) was perfectly aligned
>for every primitive type (int, long int, float...). The same as pointer
>returned from malloc().


No, the only guarantee is that there is no padding before the first
member.

The beginning of a struct is aligned so that every member of the
struct is properly aligned. Given
struct x {short y;};
there is no guarantee that any object of this type is properly aligned
for anything other than a short. Adding a member
long z;
either before or after y will insure that such an object is aligned so
that z is properly aligned. This has the side affect of also insuring
that y will also be aligned properly for a long.

As long as the member buffer from your original post is either the
first member or immediately preceded by a member with the most
stringent alignment, then buffer will also meet this alignment.

--
Remove del for email
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Iterate through a list of structure arrays of structure to get outthe field stuie_norris@yahoo.com.au C Programming 2 12-12-2012 09:18 PM
structure address = structure first field address ? Vincent De Groote C Programming 31 05-19-2009 04:09 AM
sure shot requirement for C++ with Unix Experience !!! sure interviewto day !!! Himayat66@gmail.com ASP .Net 0 02-07-2008 12:40 AM
1.Enter space bar for field names and save the field.The field shoud not get saved and an alert should be there as"Space bars are not allowed" Sound Javascript 2 09-28-2006 02:43 PM



Advertisments