Any way to get around word alignment?

Kirby

Lifer
Apr 10, 2006
12,028
2
0
I've got a structure like this:

struct
{
unsigned char a;
float b;
float c;
}value;

In memory, it puts an extra byte after my unsigned char, which messes up my data when I'm passing the structure as a pointer. I need to have it order, because I'm passing it to some other hardware via serial port. Extra padding at the end doesn't work either.

At this point the only option I can see is to add the padding to the front. The down side to this is that when I'm adding data to the structure (via serial or file i/o), I'll have to skip the first one. And I'll have to exclude it when I'm passing the data back to the serial port. It's not horrible, I was just hoping there would be a more elegant solution to cut down on the complexity.

Suggestions? :)
 

seemingly random

Diamond Member
Oct 10, 2007
5,277
0
0
Rearrange the structure elements.

Some compilers have options to pack structures but there will be a performance hit.
 

Kirby

Lifer
Apr 10, 2006
12,028
2
0
Originally posted by: seemingly random
Rearrange the structure elements.

Some compilers have options to pack structures but there will be a performance hit.

I need to have them in order since I'm passing the whole structure as binary. :/

VS Studio 2008 if it makes a difference.
 

seemingly random

Diamond Member
Oct 10, 2007
5,277
0
0
Originally posted by: nkgreen
Originally posted by: seemingly random
Rearrange the structure elements.

Some compilers have options to pack structures but there will be a performance hit.

I need to have them in order since I'm passing the whole structure as binary. :/

VS Studio 2008 if it makes a difference.
/* untested */
#pragma pack(push)
#pragma pack(1)
...structure...
#pragma pack(pop)

This can be placed in the header file where the structure is.
 

lambchops511

Senior member
Apr 12, 2005
659
0
0
For performance reasons, its generally not a good idea to pack structs (you might be splitting cache lines).

There's also a compiler's option to pack all structs in visual studio
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
Or just put a dummy byte after the character.

I have to do that because the data files that are created are read on other systems.
 

Kirby

Lifer
Apr 10, 2006
12,028
2
0
The problem with putting a dummy byte is that complicates other section of code, namely I/O to and from the struct. And the hardware I'm sending and receiving data is not designed to handle that extra byte.

The structure is only 155 bytes packed, would there really be that much of a performance hit? This really isn't high performance software anyway, just an interface program to control an embedded system.

I'm reading the like such:

unsigned char buf[1500];

fread(buf, 1, 155, file);

structure.mode = *buf++;
structure.time = bytes_to_u16(buf); //increments buf in here
structure.etc = bytes_to_float(buf);


Writing this way:

fwrite(&structure, sizeof(structure), 1, f);

As you can see, without the structure packed all of this is fubar.
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
struct
{
unsigned char a;
unsigned char dummy_byte;
float b;
float c;
}value;


For hardware that expects 9 bytes, in that particular order, you will have a problem.

struct
{
unsigned char dummy_byte;
unsigned char a;
float b;
float c;
}value;

The above will still have the proper alignment and you can transmit to the H/W device starting at the address of value.a with a buffer of 9 bytes

For code, they can manipulate the structure and extract elements from within.
The format of the structure should not matter. If it does, then the code design is trying to be fancy and expecting data blocks to be in a given location.
 

Kirby

Lifer
Apr 10, 2006
12,028
2
0
Ahh, I see. When I'm copying data to the structure, it doesn't matter what order it's in or if there's dummy byte, since my buffer is 155 bytes and I can put it wherever I want.

And to write it, I could just use fwrite(&value.a, sizeof(value) - 1, 1, f);

:beer:
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
Very good grasshopper.:D

Now go forth and share this nugget of info.:thumbsup:
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
When you take the second example, you can do block I/O with the structure using the statement you decribed

fwrite(&value.a, sizeof(value) - 1, 1, f);
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
Originally posted by: exdeath
Should always be using sizeof with pointer operations for reasons like this.

When a compiler shoves in extra bytes to force alignment; it is difficult to know where those bytes are which fouls up ones parsing of the data. Sizeof gives you the total bytes required for the structure - not the number of bytes defined for the structure.

I have a data block for avionics data of 500+ bytes. Within that data structure there are 12 pad bytes which we were unaware of initially.

When the test group and the consuming project tried to parse the output data file using XML and Java (separate apps), they ran into large amount of errors because the pad bytes were not documented.

 

seemingly random

Diamond Member
Oct 10, 2007
5,277
0
0
Originally posted by: exdeath
Should always be using sizeof with pointer operations for reasons like this.
In almost all cases, yes. But in this case, the compiler must be forced to conform to the existing data format. For maintainability, typedefs (or something similar) need to be explicitly created that force a data type and width to account for possible compiler changes. Who knows - this data format could still be in use when we're dealing with the change from 64 bit to 128 bit processors.

I know at one point, sizeof was not implemented the same in all compilers. Some included any possible trailing alignment padding and some didn't.
 

blahblah99

Platinum Member
Oct 10, 2000
2,689
0
0
Originally posted by: nkgreen
I've got a structure like this:

struct
{
unsigned char a;
float b;
float c;
}value;

In memory, it puts an extra byte after my unsigned char, which messes up my data when I'm passing the structure as a pointer. I need to have it order, because I'm passing it to some other hardware via serial port. Extra padding at the end doesn't work either.

At this point the only option I can see is to add the padding to the front. The down side to this is that when I'm adding data to the structure (via serial or file i/o), I'll have to skip the first one. And I'll have to exclude it when I'm passing the data back to the serial port. It's not horrible, I was just hoping there would be a more elegant solution to cut down on the complexity.

Suggestions? :)

You'll have to check the compiler for the proper usage, but you usually append a __packed__ attribute when defining the structure to not pad the structure with extra bytes.