Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > padding?

Reply
Thread Tools

padding?

 
 
Zach
Guest
Posts: n/a
 
      06-13-2009
I looked in the index of K&R and couldn't find anything on padding.
Could someone please explain what padding is in C programming and
illustrate it with some code. I heard it is often used in constructing
network packets.

Zach
 
Reply With Quote
 
 
 
 
Squeamizh
Guest
Posts: n/a
 
      06-13-2009
On Jun 13, 1:34*am, Richard Heathfield <(E-Mail Removed)> wrote:
> Zach said:
>
> > I looked in the index of K&R and couldn't find anything on
> > padding. Could someone please explain what padding is in C
> > programming and illustrate it with some code. I heard it is often
> > used in constructing network packets.

>
> Padding is simply a region of data storage that it is convenient to
> "waste". Precisely whom is convenienced depends on the situation.


[...]

> The tm_yday field in a struct tm is essentially padding as far as
> many people are concerned (but those who /do/ use it would
> disagree!).


Then I would strongly suggest that it isn't padding. Correct me if
I'm wrong; you seem to be saying that padding is any data that you
don't find useful in a particular situation.
 
Reply With Quote
 
 
 
 
Spiros Bousbouras
Guest
Posts: n/a
 
      06-13-2009
On 13 June, 12:35, Tor Rustad <(E-Mail Removed)> wrote:
>
> In C, padding is often used by compilers between struct members, for
> example:
>
> struct s
> {
> char c;
> <- compiler might insert 7 padding bytes here
> double d;
>
> };
>
> this because the target CPU might have alignment requirements on double
> access, or that double access is faster when e.g. aligned to e.g. 8
> byte boundery.
>
> Hence in C, you can <no> assume that
>
> struct s mys;
>
> memcpy(&mys, ...);
>
> will work, due to potential padding bytes. To load some data into a
> struct, you need to do that struct member for for struct member, unless
> using a non-standard pragma for struct packing.


What won't work ? It's not clear what you have in mind for "...".

If structures s1 and s2 are of the same type then you can do s1=s2
or memmove(&s1 , &s2 , sizeof(s2)) Both will "load some data"
to s1 without explicitly assigning to each member.

--
Ever real life has plot holes.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      06-13-2009
Tor Rustad wrote:
>
> Hence in C, you can <no> assume that
>
> struct s mys;
>
> memcpy(&mys, ...);
>
> will work, due to potential padding bytes. To load some data into a
> struct, you need to do that struct member for for struct member, unless
> using a non-standard pragma for struct packing.


Or use a static initialiser, or even just a plain old copy.

--
Ian Collins
 
Reply With Quote
 
Bjarni Juliusson
Guest
Posts: n/a
 
      06-13-2009
Tor Rustad wrote:
>> What won't work ? It's not clear what you have in mind for "...".

>
> I had a buffer in mind, which is the typical case when a network packet
> arrives or you read some data from disk.


Put another way, if you have a buffer

char buf[1024];

which has some received network packet in it, you can't do

struct packet_header *header=(struct packet_header *)buf;

and start reading the members of header and expect everything to be
fine. The packet has all members aligned according to the network
protocol, probably with very little padding, and the compiler probably
aligns for instance ints and chars differently, inserting padding in
between them or even reordering them inside the struct. There are no
guarantees (well almost no guarantees, go read the standard).

So, as an example, say you have a network protocol with a header that
contains an 8 bit packet type and a 16 bit payload length. It probably
looks like this:

offset 0: type [byte]
offset 1: length [high byte] [low byte]

Now if you declare a struct for that as

struct header{
char type;
short length;
};

on a little-endian 32 bit computer with no native 16 bit data type and a
32 bit alignment restriction, you'll probably get a struct that looks
like this in memory:

offset 0: type [byte]
offset 1: [padding] [padding] [padding]
offset 4: length [low byte] [2:nd byte]
[3:rd byte] [high byte]

If you set a pointer like that to the beginning of the buffer and try to
read the members, you'll get the right packet type, but the length will
be outside of the header data and might segfault your program, or it
might point to the second byte of the payload, or it might point to
something else entirely.

Without the padding, the length member of the struct would start at the
right place but would still read four bytes instead if the two defined
in the protocol and present in the buffer, and on top of that they would
be in the wrong order.

So that was a quick lesson in padding and network byte order.


Bjarni
--

INFORMATION WANTS TO BE FREE
 
Reply With Quote
 
Spiros Bousbouras
Guest
Posts: n/a
 
      06-14-2009
On 14 June, 00:47, Bjarni Juliusson <(E-Mail Removed)> wrote:
> The packet has all members aligned according to the network
> protocol, probably with very little padding, and the compiler probably
> aligns for instance ints and chars differently, inserting padding in
> between them or even reordering them inside the struct.


A compiler cannot reorder the fields of a structure. Paragraph 5 of
6.5.8 says:

When two pointers are compared, the result depends on the
relative locations in the address space of the objects
pointed to.
[...]
If the objects pointed to are members of the same aggregate
object, pointers to structure members declared later compare
greater than pointers to members declared earlier in the
structure,

--
If kids realised how annoying they can be they would have a lot more
appreciation for their parents.
 
Reply With Quote
 
Bjarni Juliusson
Guest
Posts: n/a
 
      06-14-2009
Spiros Bousbouras wrote:
> On 14 June, 00:47, Bjarni Juliusson <(E-Mail Removed)> wrote:
>> The packet has all members aligned according to the network
>> protocol, probably with very little padding, and the compiler probably
>> aligns for instance ints and chars differently, inserting padding in
>> between them or even reordering them inside the struct.

>
> A compiler cannot reorder the fields of a structure. Paragraph 5 of
> 6.5.8 says:
>
> When two pointers are compared, the result depends on the
> relative locations in the address space of the objects
> pointed to.
> [...]
> If the objects pointed to are members of the same aggregate
> object, pointers to structure members declared later compare
> greater than pointers to members declared earlier in the
> structure,


You are right, I apologise. In fact, it is stated more clearly in
paragraph 13 of 6.7.2.1:

Within a structure object, the [...] members [...] have
addresses that increase in the order in which they are declared.

I misremembered, and thought the only guarantee was that the first
element always ended up first in memory.

Can anyone tell me what the rationale is? It seems to me like it might
be sensible to, say, take all the char members in a struct and pack them
together at the end to preserve alignment of any int members without
lots of padding.


Bjarni
--

INFORMATION WANTS TO BE FREE
 
Reply With Quote
 
Stephen Sprunk
Guest
Posts: n/a
 
      06-14-2009
Bjarni Juliusson wrote:
> You are right, I apologise. In fact, it is stated more clearly in
> paragraph 13 of 6.7.2.1:
>
> Within a structure object, the [...] members [...] have
> addresses that increase in the order in which they are declared.
>
> I misremembered, and thought the only guarantee was that the first
> element always ended up first in memory.
>
> Can anyone tell me what the rationale is? It seems to me like it might
> be sensible to, say, take all the char members in a struct and pack them
> together at the end to preserve alignment of any int members without
> lots of padding.


It flows partially from the requirement that any initial member types
common to two structs be laid out in the same order and at the same
offsets, which is used widely for crude polymorphism. The compiler
can't know when compiling unit A what other structs will be in unit B
(which may not even be written yet) and how many, if any, of their
initial members may be in common. Therefore, the only reordering of
members that _could_ potentially be allowed is fitting later members
into the padding between earlier elements.

Once you're going to put the above restriction on reordering, you don't
lose much if you ban reordering entirely and therefore comply with the
Rule of Least Surprise -- the programmer put the members in a particular
order, so it would be logical for him to expect them to be laid out that
way in memory. If he cares about the padding (which is, in most cases,
a micro-optimization and therefore Evil(tm)), he can reorder them
himself to minimize it.

More importantly, though, I suspect that all known compilers at the time
followed this rule already, so it was probably a matter of C89
formalizing the behavior to keep future implementations from doing
something that wouldn't be compatible. Remember, ANSI's primary goal
was to standardize existing practice, not to create an ideal language.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Isaac Jaffe
 
Reply With Quote
 
Rainer Weikusat
Guest
Posts: n/a
 
      06-14-2009
Richard Heathfield <(E-Mail Removed)> writes:
> Squeamizh said:
>
>> On Jun 13, 1:34 am, Richard Heathfield <(E-Mail Removed)>
>> wrote:

> <snip>
>>
>>> The tm_yday field in a struct tm is essentially padding as far as
>>> many people are concerned (but those who /do/ use it would
>>> disagree!).

>>
>> Then I would strongly suggest that it isn't padding. Correct me
>> if I'm wrong; you seem to be saying that padding is any data that
>> you don't find useful in a particular situation.

>
> ...but that /someone/ or /something/ finds useful, and thus we can't
> just leave the padding out. Yes. That's not a formal definition,
> obviously, but it seems to me to be a very pragmatic way of looking
> at padding.


It is nevertheless wrong: 'Padding' is additional storage beyond the
one necessary to hold, say, the data values of a C struct, which is
used to achieve some effect beyond what is specified in the
C-standard, typically, to conform to ABI-requirements regarding
alignment of objects of a particular size (for instance, '4-byte
integers must always be stored at addresses evenly divisble by four')
in order to be able to generate more efficient machine code (for
instance, because properly aligned 4-byte values can be manipulated
with machine instructions operating on 'words' of data). This is
something different than 'data members someone may consider to be
useless' (and hence, 'a waste of space').
 
Reply With Quote
 
Giorgos Keramidas
Guest
Posts: n/a
 
      06-15-2009
On Sun, 14 Jun 2009 04:00:08 +0200, Bjarni Juliusson <(E-Mail Removed)> wrote:
> You are right, I apologise. In fact, it is stated more clearly in
> paragraph 13 of 6.7.2.1:
>
> Within a structure object, the [...] members [...] have
> addresses that increase in the order in which they are declared.
>
> I misremembered, and thought the only guarantee was that the first
> element always ended up first in memory.
>
> Can anyone tell me what the rationale is? It seems to me like it might
> be sensible to, say, take all the char members in a struct and pack
> them together at the end to preserve alignment of any int members
> without lots of padding.


For a struct with no aggregate members, this may not be quite as useful
(but then I may also be missing an important detail behind the rule).
But it seems quite sensible for code that includes structs inside other
structs, i.e.:

struct methods;

struct object {
long magic;
size_t size;
long type;
struct methods *fptr;
size_t nfptr;
};

struct myobject {
struct object parent;
char mydata[10];
};

This is commonly used to 'tag' structures of different types. If the
compiler was allowed to reorder the fields of `myobject', it would be
quite unpredictable where myobject.parent would end up.

 
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




Advertisments