padding?

B

Ben Bacarisse

Tim Rentsch said:
In

struct s {
unsigned foo : 4;
unsigned : 12;
unsigned bas : 16;
};

would you say the data member between foo and bas is there as
padding?

Since you can't access its value at all (stupid tricks with unsigned
char pointers aside), and that value is therefore irrelevant, yes.
If we have

struct s x, y;
memset( &y, 0, sizeof y );
x = y;

is the unnamed bit-field member guaranteed to hold zeroes, or
not?

In y, yes, but they're irrelevant; in x, they're not even guaranteed to
be zero.
(because structures are not allowed to have padding at the beginning)?

Structures are not allowed to have _implementation-inserted_ padding
_bytes_ at the beginning. You, as the user-programmer, are allowed to
add as much padding of your own as pleases you. There is nothing in the
Standard to stop you from declaring

struct t {
unsigned char padding[37];
long int single_data_member;
unsigned char more_padding[51];
}

Do not be surprised to find extra padding added after _your_ member
called padding, and before or after more_padding.

Tell me, did you _really_ not know all this, or are you being an awkward
arsehole just to make the point that you _can_ be an awkward
arsehole?

What on Earth is the point of being rude? Tim seems to be someone who
relishes detail. If you want to avoid such detailed arguments, then
simply don't reply. If you do, then you will find there is almost
always some valid point being made.

In this case, I suspect he was moved to post by the first remark he
quoted:

since his example was of a data member which both of you agree is
padding. From what follows that quote, it is clear that you did not
mean it as written. You were saying something along the lines of
"padding is never a proper data member at all" or better yet you could
have joined the two sentences to show you were extending this remark
with "the defining characteristic of padding...".

It is both the a major strength and tragic weakness of Usenet that
these sorts of discussions are what it does best.
 
K

Keith Thompson

That depends on whether that is a political or a technical "must". If
there is reasonable expectation that it may in the future be used, and
can then get other values, it's not. If it's only required to be zero
out of a show of future planning, it's padding. I admit that this may,
for an outsider, be difficult to judge.

There are at least three distinct meanings of "padding".

The C standard defines "padding bits" for integer types, and "padding
bytes" for structs. (It doesn't define padding for floating-point or
pointer types, because it doesn't specify enough about either for the
concept to be meaningful -- though I suppose it could do so for FP.)

What we're talking about here is what "padding" means in a non-C
context. I know of no rigorous definition (say, one that excludes
foam rubber), and no way to resolve any disagreements about whether an
unused byte in an IP packet qualifies as "padding".
 
T

Tim Rentsch

Since you can't access its value at all (stupid tricks with unsigned
char pointers aside), and that value is therefore irrelevant, yes.

C trivia question: Is it possible to access the value of an unnamed
bit-field in a way that's portable and not implementation dependent?

Answer: of course there are implementation dependent ways (besides
using unsigned chars, there are other kinds of type punning, or
reading/writing a binary file), but it may surprise some people to
know that there is also a portable way to do so:

struct s {
unsigned foo : 4;
unsigned : 12;
unsigned bas : 16;
};

struct t {
unsigned foo : 4;
unsigned hidden : 12;
unsigned bas : 16;
};

union s_and_t {
struct s s;
struct t t;
} s_and_t;

/* now using s_and_t.t.hidden will access */
/* the unnamed bit-field in s_and_t.s */

Furthermore this technique could be useful in implementing a
semi-opaque type, using one type as the public type, and another
type to access the "hidden" members.

In y, yes, but they're irrelevant; in x, they're not even guaranteed to
be zero.

In fact I think they are. I can't find any provision in the
Standard that suggests they needn't be copied along with every
other member. There is one case where unnamed bit-fields are
handled differently, and that is initialization. 6.7.8 p 9 says:

Except where explicitly stated otherwise, for the purposes of
this subclause unnamed members of objects of structure and union
type do not participate in initialization. Unnamed members of
structure objects have indeterminate value even after
initialization.

But note 6.7.8 p 13:

The initializer for a structure or union object that has
automatic storage duration shall be either an initializer list
as described below, or a single expression that has compatible
structure or union type. In the latter case, the initial value
of the object, including unnamed members, is that of the
expression.

Considering this, and considering the absence of any statement
that says unnamed bit-fields are treated differently during
assignment, I propose the most reasonable conclusion is that the
Standard expects them to be copied just as other members are.

(because structures are not allowed to have padding at the beginning)?

Structures are not allowed to have _implementation-inserted_ padding
_bytes_ at the beginning. You, as the user-programmer, are allowed to
add as much padding of your own as pleases you. There is nothing in the
Standard to stop you from declaring

struct t {
unsigned char padding[37];
long int single_data_member;
unsigned char more_padding[51];
}

Do not be surprised to find extra padding added after _your_ member
called padding, and before or after more_padding.

I admit, my question here is to a degree deliberately obtuse.
However, there's an important difference between the question
that I asked and the example "padding" members in the example
above, in that there is nothing in the Standard that suggests
that it would put the latter under the label of 'padding', whereas
as there is a _hint_ of such suggestion for unnamed bit-fields.
(A footnote in 6.7.2.1 p 11.) I don't really think this
means that unnamed bit-fields are padding the sense that
normative passages in the Standard use the term, but
certainly we should expect the Standard to be consistent
as to its viewpoint on this question. Shouldn't we?

Tell me, did you _really_ not know all this, or are you being an awkward
arsehole just to make the point that you _can_ be an awkward arsehole?

I usually don't think of myself as an ass**** (either awkward or
otherwise), but if/when I do there doesn't seem to be any point to
making a statement solely for the purpose of pointing that out.

In this particular case, there are several points that I think
are of general interest to newsgroup readers. One: is structure
assignment required to copy unnamed bit-fields? (I believe it
is, other people may have different opinions.) Two: there is a
portable way to access values of bit-field members. Three: the
word 'padding' is used in several different senses in the
Standard, mostly without any definition, and in fact it's not
clear how many different senses there are, or which ones are
which in all cases. So, when making a statement about padding in
comp.lang.c, it's a good idea to be clear about which sense of
the word one is referencing, especially if it's different from,
or might be different from, the several ways that the Standard
uses the term.
 
T

Tim Rentsch

Keith Thompson said:
There are at least three distinct meanings of "padding".

The C standard defines "padding bits" for integer types, and "padding
bytes" for structs. (It doesn't define padding for floating-point or
pointer types, because it doesn't specify enough about either for the
concept to be meaningful -- though I suppose it could do so for FP.)

What we're talking about here is what "padding" means in a non-C
context. I know of no rigorous definition (say, one that excludes
foam rubber), and no way to resolve any disagreements about whether an
unused byte in an IP packet qualifies as "padding".

There is also the footnote in 6.2.6.1 p 6, which mentions "padding
bits", presumably meaning to cover "padding bytes" for structs/unions,
and also the unused bits between (or after) members when one of
them is a bit-field. (Of course, "padding bytes" also covers
extra bytes at the end of a union.)
 
T

Tim Rentsch

Ben Bacarisse said:
Tim Rentsch said:
[long and seemingly obtuse response comments]

Tell me, did you _really_ not know all this, or are you being an awkward
arsehole just to make the point that you _can_ be an awkward
arsehole?

What on Earth is the point of being rude?

I took the question to mean that he didn't see the point of what
I was saying, and since he didn't expect me to behave in such a
pointless way, was confused about whether I'd turned stupid or
was deliberately yanking his chain. In a way it says something
good that (apparently) he considers both relatively unlikely.

In this case his comment served a useful purpose in that it let
me know he was confused about the point of my response, and that
let me respond to it more appropriately. Also, I confess that I
have been guilty of similar comments responding to other people
in the past, so I think it's only fair to forgive such comments
when they are said to me. Anyway, no worries on my part.
Tim seems to be someone [...snip...]

Thank you for the implied compliment (at least I took it as such)
on my newsgroup postings.
 
K

Keith Thompson

Tim Rentsch said:
Three: the
word 'padding' is used in several different senses in the
Standard, mostly without any definition, and in fact it's not
clear how many different senses there are, or which ones are
which in all cases.

As far as I can tell, the standard is *mostly* consistent about
using the term "padding" only to refer to "padding bits", which occur
within an integer representation, and "padding bytes", which occur in
a struct or union representation. (I'm not sure what it says about
the gaps between bit fields; I'll look into that later.)

A footnote in 6.7.2.1p11 says:

An unnamed bit-field structure member is useful for padding to
conform to externally imposed layouts.

and 7.19 talks about "padding" streams with spaces or null characters.
So, when making a statement about padding in
comp.lang.c, it's a good idea to be clear about which sense of
the word one is referencing, especially if it's different from,
or might be different from, the several ways that the Standard
uses the term.

Agreed.
 
K

Keith Thompson

Tim Rentsch said:
There is also the footnote in 6.2.6.1 p 6, which mentions "padding
bits", presumably meaning to cover "padding bytes" for structs/unions,
and also the unused bits between (or after) members when one of
them is a bit-field. (Of course, "padding bytes" also covers
extra bytes at the end of a union.)

Hmm. I suspect that was a typo for "padding bytes".

Here's the context:

When a value is stored in an object of structure or union type,
including in a member object, the bytes of the object
representation that correspond to any padding bytes take
unspecified values.

[footnote]
Thus, for example, structure assignment need not copy any padding
bits.

The quoted footnote is from N1256. In the original C99 standard, the
foonote says:

Thus, for example, structure assignment may be implemented
element-at-a-time or via memcpy.

The change was made in TC2 in response to DR #222
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_222.htm>. The
wording of the footnote in N1256 matches the wording in both DR #222
and TC2.
 
T

Tim Rentsch

Keith Thompson said:
As far as I can tell, the standard is *mostly* consistent about
using the term "padding" only to refer to "padding bits", which occur
within an integer representation, and "padding bytes", which occur in
a struct or union representation. (I'm not sure what it says about
the gaps between bit fields; I'll look into that later.)

A footnote in 6.7.2.1p11 says:

An unnamed bit-field structure member is useful for padding to
conform to externally imposed layouts.

and 7.19 talks about "padding" streams with spaces or null characters.

I think you're right about "padding bits", which AFAICS is used
almost exclusively in connection with representation of integer
types. There is one exception in a footnote in 6.2.6.1 p 6,
talking about structure assignment.

For other uses, I think it's less clear. I find only one use of
the term "padding bytes" (coincidentally also in 6.2.6.1p6). All
other uses of the term padding (not counting the "padding bits"
cases) just say padding, not padding bytes. That actually seems
more sensible, since padding in between structure members can be
either bits or bytes. It is true that uses of "padding" not
counting the "padding bits" for integer types are almost all
given in connection with struct/union types (the exception
mentioned above in connection with streams is the only one
I'm aware of). But mostly other uses of "padding" seem to
mean unused memory, _either_ bits or bytes, after struct/union
members (and possibly before subsequent members in the case
of a struct).
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
There is also the footnote in 6.2.6.1 p 6, which mentions "padding
bits", presumably meaning to cover "padding bytes" for structs/unions,
and also the unused bits between (or after) members when one of
them is a bit-field. (Of course, "padding bytes" also covers
extra bytes at the end of a union.)

Hmm. I suspect that was a typo for "padding bytes".

Here's the context:

When a value is stored in an object of structure or union type,
including in a member object, the bytes of the object
representation that correspond to any padding bytes take
unspecified values.

[footnote]
Thus, for example, structure assignment need not copy any padding
bits.

The quoted footnote is from N1256. In the original C99 standard, the
foonote says:

Thus, for example, structure assignment may be implemented
element-at-a-time or via memcpy.

The change was made in TC2 in response to DR #222
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_222.htm>. The
wording of the footnote in N1256 matches the wording in both DR #222
and TC2.

It seems more likely that "padding bits" is what was
actually meant, meaning to cover both the cases of
whole bytes in between members, and also partial
bytes (bits) in between members.

But it raises an interesting question. If there is
a partial byte of unused memory (following a bit-field
member, and before the subsequent member), are those
bits guaranteed to be left unchanged by assignment
to the bit-field member (or other members, but that's
the obvious one)? Those bits don't correspond to
any padding bytes, and so aren't covered by 6.2.6.1p6.
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Hmm. I suspect that was a typo for "padding bytes".
[...]
It seems more likely that "padding bits" is what was
actually meant, meaning to cover both the cases of
whole bytes in between members, and also partial
bytes (bits) in between members.

But the phrase "padding bits" is specifically used to refer certain
bits in integer representations. Even if "padding bits" is what was
meant here, there needs to be some more wording clarifying just what
that means.
But it raises an interesting question. If there is
a partial byte of unused memory (following a bit-field
member, and before the subsequent member), are those
bits guaranteed to be left unchanged by assignment
to the bit-field member (or other members, but that's
the obvious one)? Those bits don't correspond to
any padding bytes, and so aren't covered by 6.2.6.1p6.

I don't think there'd be any benefit in guaranteeing that such bits
are unchanged. On the other hand, an implementation would have to go
out of its way to leave such bits undefined. On the other other hand,
it might make sense to do so; for example, an implementation might try
to guarantee that all padding is set to zero (unless you use something
like memset to set it to something else).
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
There is also the footnote in 6.2.6.1 p 6, which mentions "padding
bits", presumably meaning to cover "padding bytes" for structs/unions,
and also the unused bits between (or after) members when one of
them is a bit-field. (Of course, "padding bytes" also covers
extra bytes at the end of a union.)

Hmm. I suspect that was a typo for "padding bytes".
[...]
It seems more likely that "padding bits" is what was
actually meant, meaning to cover both the cases of
whole bytes in between members, and also partial
bytes (bits) in between members.

But the phrase "padding bits" is specifically used to refer certain
bits in integer representations. Even if "padding bits" is what was
meant here, there needs to be some more wording clarifying just what
that means.

I agree, absolutely.

I don't think there'd be any benefit in guaranteeing that such bits
are unchanged. On the other hand, an implementation would have to go
out of its way to leave such bits undefined. On the other other hand,
it might make sense to do so; for example, an implementation might try
to guarantee that all padding is set to zero (unless you use something
like memset to set it to something else).

If I had to bet (at even money, presumably) on how
the committee would vote on this question, I would
bet the vote would go in favor of having the values
of unused bits (with less than a byte's worth)
having unspecified values. (Can a single bit
even hold a trap representation?)

However, I meant only to ask the question of what
the Standard currently does say on the question, not
what it should say.
 
R

Richard Bos

Keith Thompson said:
There are at least three distinct meanings of "padding".

The C standard defines "padding bits" for integer types, and "padding
bytes" for structs.

As far as I can tell, both of those fall under my definition of padding
above. In neither case is the contents of those bits relevant to the
programmer.
What we're talking about here is what "padding" means in a non-C
context. I know of no rigorous definition (say, one that excludes
foam rubber), and no way to resolve any disagreements about whether an
unused byte in an IP packet qualifies as "padding".

If it's actually unused, again, I think that falls under the above
definition of "a member whose only important feature is its size, and
whose contents is irrelevant".

Richard
 
R

Richard Bos

Tim Rentsch said:
I admit, my question here is to a degree deliberately obtuse.

I usually don't think of myself as an ass**** (either awkward or
otherwise), but if/when I do there doesn't seem to be any point to
making a statement solely for the purpose of pointing that out.

Well, I'm sorry, but I find post-modernism only extremely irritating in
a lit crit context, but downright anathema in a computing discussion. So
don't expect me to take it seriously.

Richard
 
T

Tim Rentsch

Well, I'm sorry, but I find post-modernism only extremely irritating in
a lit crit context, but downright anathema in a computing discussion. So
don't expect me to take it seriously.

I see you ignored all the technical content of my message
(82 lines) and chose to focus instead on just the four
lines quoted above (three of which are there only because
of your previous somewhat rudely phrased question). In
the earlier case it seemed right to give you the benefit
of the doubt. The doubt is now removed; clearly what I
should expect in the future is that you might ignore any
statement at any time whenever it suits your purposes.
 
N

Nick Keighley

I might, if say I was describing the format of a data packet.
I don't consider it "padding" in the C sense of the word.

I think the "stupid trick" with unsigned char can't be ignored.
C trivia question:  Is it possible to access the value of an unnamed
bit-field in a way that's portable and not implementation dependent?

no. Its very position is implementation defined
Answer:  of course there are implementation dependent ways (besides
using unsigned chars, there are other kinds of type punning, or
reading/writing a binary file), but it may surprise some people to
know that there is also a portable way to do so:

surprise me
    struct s {
        unsigned foo : 4;
        unsigned     : 12;
        unsigned bas : 16;
    };

    struct t {
        unsigned foo    : 4;
        unsigned hidden : 12;
        unsigned bas    : 16;
    };

    union s_and_t {
        struct s s;
        struct t t;
    } s_and_t;

    /* now using   s_and_t.t.hidden   will access */
    /* the unnamed bit-field in   s_and_t.s        */

....and invoke Undefined Behaviour. You've replaced IB with UB.


<snip>
 
T

Tim Rentsch

Nick Keighley said:
I might, if say I was describing the format of a data packet.
I don't consider it "padding" in the C sense of the word.


I think the "stupid trick" with unsigned char can't be ignored.


no. Its very position is implementation defined


surprise me


...and invoke Undefined Behaviour. You've replaced IB with UB.

No, this is defined behavior, not undefined behavior.
Please see 6.5.2.3 p 5.
 
N

Nick Keighley

No, this is defined behavior, not undefined behavior.
Please see 6.5.2.3 p 5

what's the section titled, "Structure and Union Members"?
Or could you quote it? I don't have an ISO standard handy.

This is the "common initial sequence" bit? Interesting.
 
R

Richard Bos

Tim Rentsch said:
I see you ignored all the technical content of my message
(82 lines) and chose to focus instead on just the four
lines quoted above

Yes, for exactly the reasons outlined above. I have better things to do
with my time than dragging someone's honest intentions out of them like
so many horse's teeth. You do not make a good Socrates, and while you
would probably make a good Derrida, I do not see this as a goal to be
encouraged. I'll pay attention to you again when you have not only
technical content, but also a discernable point.

Richard
 
T

Tim Rentsch

Nick Keighley said:
what's the section titled, "Structure and Union Members"?
Or could you quote it? I don't have an ISO standard handy.

This is the "common initial sequence" bit? Interesting.

Yes, the common initial sequence guarantee. Here is the text of
paragraph 5:

One special guarantee is made in order to simplify the use
of unions: if a union contains several structures that
share a common initial sequence (see below), and if the
union object currently contains one of these structures, it
is permitted to inspect the common initial part of any of
them anywhere that a declaration of the complete type of the
union is visible. Two structures share a common initial
sequence if corresponding members have compatible types
(and, for bit-fields, the same widths) for a sequence of one
or more initial members.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top