Re: Structure size directives



Keith Thompson wrote:
Tor Rustad <tor_rustad@xxxxxxxxxxx> writes:

[...]

In my opinion, if a compiler is going to support structure members
that don't have the alignment for the member's type, it's the
compiler's job to generate code that will access that member in a way
that (apart from performance and code size) is indistinguishable from
accessing an aligned member.
Well, I don't think most system programmers agrees with you, since
this leads to code bloat, hiding of translation details and do hurt
performance.

System programmers who are concerned about code bloat et al can just
not use packed structures.

When you target a specific architecture, the alignment requirements are know apriori, so system developers do make use of explicit alignment and knows what they are doing.


C is close to a WYSIWYG language, which helps in generating compact,
predictable code, the language add little obfuscation for system
developers. The spirit of C, is to trust the programmer and not stop
him/her from doing exactly what asked.

If I instruct the compiler to do explicit alignment, that is what it
should provide. I can understand if application programmers don't care
much if the compiler generate some fix-up code to handle alignment
issues, but others don't want it.

Here's my point. Suppose a compiler allows a declaration like this:

struct foo {
char c;
int i;
};
#pragma pack(struct foo)
struct foo obj;
obj.i = 42;

Assume sizeof(int)==4, and int normally requires 4-byte alignment.
Assume that without the #pragma pack, "i" would be allocated at an
offset of 4 bytes, and with the #pragma pack, it would be allocated at
an offset of 1 byte (misaligned).

*If* the compiler supports this, then it had better let me access
obj.i by name without causing my program to crash. It can do whatever
it needs to do to make this happen; I don't much care about the
machine-code details, any more than I care about how it would access
obj.i if it weren't misaligned.

There are really two different cases here, you talk about the usage of "pack" to minimize padding in a struct, while I talk about the "pack (n)" usage, which specify alignment(s) of struct members. :)

I must admit that I have never seen the former "pack" usage, and have never wanted this type of "packing" in my own code. If the memory available is minimal and you like to minimize the amount of storage used by structure objects, we can manually re-arrange struct members like this:

struct foo_alt
{
int i; /* typically word aligned */
char c; /* typically byte aligned */
};

and then compile program with size optimization switch on. The programmer typically need to think about both *data* and *code* size. The solution above, should minimize the total size, while "pragma pack"
may bloat the *code* size.

Hence, the struct members can be manually sorted by alignment requirements, like e.g.

struct foo_general
{
/* put type double members here... */
/* put type long members here... */

int i;
/* put more type int members here... */

char c;
/* put more type char members here... */
};

The struct can even be generated by another program. A recent project of mine, I used this technique to generate a monster struct (among other stuff):

$ cat iso_bitmap.def

/*
* This file, "iso_bitmap.def", is used by iso_gen_struct.c
* to generate <iso_bitmap_def.h>
*
* Reference: ISO 8583:1993 Table 7A.
*/

/* Name No Type Length Format*/
EXPAND_FIELD(MESSAGE_TYPE_ID, 0, N, 4, FIXED);
EXPAND_FIELD(BITMAPS , 1, B, 16, FIXED);
.....
<lots of other struct members snipped>

The C program using the <iso_bitmap_def.h> header file, make no assumptions of ordering of members within the struct, or the offsets of it's struct members. So, if I wanted, I could generate the struct with members sorted by the alignment requirements.

Hmm.. instead of "pragma pack", it appears to me that a "pragma align_sort" is more useful, telling compiler there is no need for ordering the struct members in the order given by the declaration of the struct.

I've worked in languages that have the equivalent of packed
structures, and this is what they do.
And in such languages, packing comes with a price.. e.g. what could
have been done via a single load, now require two loads. In a HPC
cluster, you don't want such "packing" on a memory bound programs.

Of course it comes with a price.

I don't know that you wouldn't want such packing in an HPC cluster, or
on any other system; the savings in memory *might* outweigh the costs.
It's going to depend on the application, and it should be up to the
programmer.

I was above referring to HPC programs, which was run-time memory bound, (not talking about memory size), and not suggesting that memory size constraints wasn't important for HPC problems.

Now if you want to argue that "#pragma pack" is a bad idea, I won't
necessarily disagree with you. I don't think I've ever used it
myself, and I don't necessarily advocate adding it to the standard.
I don't object either to providing the feature, or to leaving it out.
I object to implementing it badly.

I object to adding a feature, which do some code-bloat behind the scene for fix-ups. However, having a directive which inform the compiler that the struct member ordering can be rearranged (with the most strictly aligned members first), I'm less negative to, since this shouldn't give any code bloat for fix-ups, or mis-aligned members.

--
Tor <bwzcab@xxxxxxxxx | tr i-za-h a-z>
.



Relevant Pages

  • Re: [PATCH] drm: Only use DRM_IOCTL_UPDATE_DRAW compat wrapper for compat X86.
    ... Only X86 32-bit uses a different alignment for "unsigned long long" ... typedef struct drm_update_draw32 { ... unsigned int type; ... structure, access members as unaligned). ...
    (Linux-Kernel)
  • Re: procedure parameter struct order
    ... the members of this struct would always have the same order on ... >> members in the order they are declared. ... Or if there even is a stack as such, ... > compiler would be quite correct if, behind the scenes, all it pushed on ...
    (comp.lang.c)
  • Re: Uninitialized memory, malloc and unsigned char
    ... the structure or union object may be a trap representation. ... I think this ensures that the holes between sturct members do not ... affect validity of the struct. ...
    (comp.std.c)
  • Re: "common initial sequence" rule = non-obvious constraints on padding?
    ... of any member struct of a union which currently contains such a struct ... anywhere that union type is visible. ... I'm sure that on the DS9000, the linker searches the complete program for unions and adds random padding between structure members in a way that breaks this assumption. ... compatible, you can declare the same object twice, using both types, without breaking the program. ...
    (comp.std.c)
  • Re: struct sockaddr_XYZ formats portable?
    ... >> If however, for some reasons, you want to send a particular ... Byte order isn't the problem as the multi-byte members like port are ... order and overall struct sizes were equal so ... explicit alignment is specified in the headers. ...
    (comp.unix.programmer)