Bitwise Operator Effects on Padding Bits

S

Shao Miller

Ben said:
It's a bit stronger than that. Promotion produces a value not a
representation. I would say that any promoted operand has no padding
bits at all.

Really? Surely the "the value is converted to an int" implies that the
representation for an 'int' applies, for example, including any
implementation-defined padding bits, doesn't it?

To suggest that we can have a value with a non-bit-field type but
without a consistent representation for the type (not the value) strikes
me as unusual with 3.14p1 and 3.17p1 in mind. In 6.5.16.1p4 we see
details of "...converted...to int width..." which, to me, suggests that
even intermediate, non-addressable values adhere to the type
representation (for non-bit-fields).

If you are suggesting that the padding bits of results are defined
inaccessibly except via object representation inspection, well that's
rather the nature of my line of questioning...
I'd say the same even if the type does not change.

The same meaning "theoretically, there are no padding bits associated
with the intermediate values during evaluation, because they are
inaccessible until inspected via object representation"?
... ... ...
My point is that promoted results don't have a representation.

They can have a type but need not have a consistent type representation?
At some level it doesn't matter either way. Imagine an implementation
that adds 107 padding bits to every promoted int. Since you can't
inspect these bits

That's really rather what I'm asking about. I apologize if it's not
clear. Please allow me to ask it differently: If we complement an 'int'
and store the result and inspect the object representation, are we
defined to discover that padding bits from the original have been
complemented in the stored result? I doubt it, but am uncertain.
and they have no effect on the value, how could you
tell? I think it is simper to say they don't form part of the value
that results from a promotion.

Well I agree, they are a separate group of bits that also possibly
compose the type representation necessary for the value. But as for
inspection, see the question just above.
But if it pleases you to think of them being there, why not? In fact,
lets just say that all padding bits stay with their values during
promotion and they all get toggled by ~. Now what? As far as I can
tell, such a language has the same semantics as the one I am describing.

I think I understand your perspective; it's about accessibility of the
information regarding any possible padding bits. Since we work with
values and sign primarily, padding bits are pretty far out-of-scope for
theory. So really object representation inspection is the only area
where padding bits are in-scope. Since they're in-scope for this area,
I'd like to understand them better, and how useful information about
them is, perhaps in identification of environmental characteristics such
as parity representation or positional grouping of bits.

Thank you.
 
B

Ben Bacarisse

[I will snip a lot because there seems to be only one issue here]
Shao Miller said:
Ben Bacarisse wrote:

That's really rather what I'm asking about. I apologize if it's not
clear. Please allow me to ask it differently: If we complement an
int' and store the result and inspect the object representation, are
we defined to discover that padding bits from the original have been
complemented in the stored result? I doubt it, but am uncertain.

It is certain that it can't be true in general (if, say, any padding bit
set to 1 represents a trap, then ~0 can't invert the padding bits) so
why bother speculating about some other cases?

I don't see any wording in the standard that says the padding bits are
ever predictable other than the words that say the trap representations
can't come about from safe arithmetic operations (and this includes ~).

For this reason, I prefer to think of the values that float about during
expression evaluation as being pure -- either pure binary with no
padding bits (but with a specific signed representation) or even as pure
mathematical values; the type with which they are associated being used
only to determine what words like "bit" means.
Well I agree, they are a separate group of bits that also possibly
compose the type representation necessary for the value. But as for
inspection, see the question just above.

By all means consider the value of ~0 to include any padding bits. What
you can't do is inspect them. What gets put into an object is *a*
representation of the value not *the* representation so you can't say
anything about them once they become amenable to inspection.
I think I understand your perspective; it's about accessibility of the
information regarding any possible padding bits. Since we work with
values and sign primarily, padding bits are pretty far out-of-scope
for theory. So really object representation inspection is the only
area where padding bits are in-scope. Since they're in-scope for this
area, I'd like to understand them better, and how useful information
about them is, perhaps in identification of environmental
characteristics such as parity representation or positional grouping
of bits.

There are there for inspection in the object representation but since I
don't even think they need to be persistent I doubt there is much to be
gained from looking.
 
S

Shao Miller

Ben said:
[I will snip a lot because there seems to be only one issue here]
Shao Miller said:
Ben Bacarisse wrote:
That's really rather what I'm asking about. I apologize if it's not
clear. Please allow me to ask it differently: If we complement an
int' and store the result and inspect the object representation, are
we defined to discover that padding bits from the original have been
complemented in the stored result? I doubt it, but am uncertain.

It is certain that it can't be true in general (if, say, any padding bit
set to 1 represents a trap, then ~0 can't invert the padding bits) so
why bother speculating about some other cases?

Aha. Perhaps an example might help.

Please consider the Hamming Code with N == 7, K == 4. There are three
parity checking bits. There are 2^K == 16 valid values with their
corresponding, parity-correct representations. But the number of
representations is 2^N == 128.

For each valid value, complementing the entire representation (including
parity bits) results in the correct representation (including parity
bits) for the complemented value bits; a case where complementing parity
makes perfect sense.

Each of the 128 - 16 == 112 remaining representations could be a trap
representation.

If our environment was specialized to be a system which pulls bytes from
a network, populates integer objects and performs mathematics on them,
we might desire this sort of scenario (albeit with greater N and K due
to the CHAR_BIT minimum, for instance).

Just the same as an invalid pointer value loaded into an address
register could be troublesome, perhaps we, the programmers, have the
opportunity to perform some integrity checks on the object
representation (via 'unsigned char') before we actually use the value
with some other integer type (which could effectively load a trap
representation into an arithmetic register and be troublesome).

So the sense that I'm getting from some responses here is not that the C
Standard limits integer representations at all. Otherwise, unary '~'
complementing each bit in an operand could be perceived as something of
a constraint on representations in that whatever the uses (if any) of
padding bits are, they must be consistent with complementing.
I don't see any wording in the standard that says the padding bits are
ever predictable other than the words that say the trap representations
can't come about from safe arithmetic operations (and this includes ~).

Yeahbut that's what I'm asking. 6.5.3.3p4 says "operand" rather than
"value". That's wording which could be interpreted to include padding
bits. The fact that we shall not produce a trap representation other
than as part of an exceptional condition could be viewed as a constraint
on what padding bits are used for.
For this reason, I prefer to think of the values that float about during
expression evaluation as being pure -- either pure binary with no
padding bits (but with a specific signed representation) or even as pure
mathematical values; the type with which they are associated being used
only to determine what words like "bit" means.
Ok.


By all means consider the value of ~0 to include any padding bits. What
you can't do is inspect them. What gets put into an object is *a*
representation of the value not *the* representation so you can't say
anything about them once they become amenable to inspection.

So your stance here is that in 'x = ~x;', we have the read of 'x' result
in an abstract mathematical value, the value bits are complemented, then
those bits are stored back into 'x' along with theoretically random
padding bits, which have theoretically zero state correlation to the
padding bits in the previous object representation for 'x'. Is that right?
There are there for inspection in the object representation but since I
don't even think they need to be persistent I doubt there is much to be
gained from looking.

Persistence! That is an excellent point! If I copy the object
representation of a 'struct' which includes padding and immediately
thereafter compare the object representations of the original and the
copy, am I guaranteed to find that padding bits are the same? I should
think so, given that 'unsigned char' has no padding bits.

When 6.2.4p2 says "last-stored value", would it be a tad more accurate
to state that an object retains its "last-stored object representation",
instead? Otherwise, I'm imagining padding bits being allowed to
flip-flop at random on a conforming implementation. After all, it's not
until we access as a character type that the object could be considered
to have no padding bits.

Thanks again!
 
L

lawrence.jones

Shao Miller said:
That's really rather what I'm asking about. I apologize if it's not
clear. Please allow me to ask it differently: If we complement an 'int'
and store the result and inspect the object representation, are we
defined to discover that padding bits from the original have been
complemented in the stored result?

No. *All* operators operate on values, not object representations, and
padding bits (by definition) are not part of the value. Their settings
are always unspecified.
 
L

lawrence.jones

Shao Miller said:
Speaking of non-normative footnotes, that footnote's sibling, footnote
45, causes me a bit of confusion. If we use '~' to produce a negative
zero and it's a trap representation, what kind of exceptional condition
is that?

Applying the ~ operator to an operand that produces such a value, which is
explicitly undefined behavior.
 
B

Ben Bacarisse

Shao Miller said:
Ben said:
[I will snip a lot because there seems to be only one issue here]
Shao Miller said:
Ben Bacarisse wrote:
At some level it doesn't matter either way. Imagine an implementation
that adds 107 padding bits to every promoted int. Since you can't
inspect these bits
That's really rather what I'm asking about. I apologize if it's not
clear. Please allow me to ask it differently: If we complement an
int' and store the result and inspect the object representation, are
we defined to discover that padding bits from the original have been
complemented in the stored result? I doubt it, but am uncertain.

It is certain that it can't be true in general (if, say, any padding bit
set to 1 represents a trap, then ~0 can't invert the padding bits) so
why bother speculating about some other cases?

Aha. Perhaps an example might help.

I don't think so. An example of how unspecified behaviour might be
implemented does not address the question. C certainly permits an
implementation to preserve or to manipulate the padding bits is almost
any way so there will be examples where useful things will happen. In
general, you can't rely on what the padding bits end up holding but I
have no problem with an implementation that says a lot more.

My argument that values don't have padding bits is just an abstract view
of how I think it helps to look at portable C which was, I think, the
original context. Some implementations may be a lot more specific but
that's a lot less interesting.

Yeahbut that's what I'm asking. 6.5.3.3p4 says "operand" rather than
"value". That's wording which could be interpreted to include padding
bits. The fact that we shall not produce a trap representation other
than as part of an exceptional condition could be viewed as a
constraint on what padding bits are used for.

If you want to read it that way. I don't have any enthusiasm for an
argument about what an operand is -- its clear we don't agree about many
of the plain terms of the standard. But no matter, you are half way
there. Because the standard says "(promoted) operand" rather than
"value" all you now need is some wording that lets you be convinced that
this representation has to get back into an object unchanged and you
will have the assurance you are looking for. Since padding bits in ints
(the usual promoted type for ~) are rare you won't have much trouble
with implementations that don't conform because they took another
reading of the standard.
So your stance here is that in 'x = ~x;', we have the read of 'x'
result in an abstract mathematical value, the value bits are
complemented, then those bits are stored back into 'x' along with
theoretically random padding bits, which have theoretically zero state
correlation to the padding bits in the previous object representation
for 'x'. Is that right?

In the general case, yes. In other words, your paraphrasing is the most
one be assured of. Some implementations may be far more specific and
won't then fit with the view I've presented. That, to me is the right
way round in that I am happier to permit specific exceptions to a
general rule that to have a specific rule that I have to keep reminding
myself does not apply in general.

Persistence! That is an excellent point! If I copy the object
representation of a 'struct' which includes padding and immediately
thereafter compare the object representations of the original and the
copy, am I guaranteed to find that padding bits are the same? I
should think so, given that 'unsigned char' has no padding bits.

Why can't the padding in the struct change its setting between the copy
and the compare?
When 6.2.4p2 says "last-stored value", would it be a tad more accurate
to state that an object retains its "last-stored object
representation", instead?

If that was intended meaning, yes. Do you know if that was the intent
or did the committee mean exactly what they wrote?

Since I have no interest in writing a program where the distinction
matters, I am happy with either meaning; and if I ever have to write
such a program I'll take the interpretation that gives me the least
guarantees just to be on the safe side.
Otherwise, I'm imagining padding bits being
allowed to flip-flop at random on a conforming implementation. After
all, it's not until we access as a character type that the object
could be considered to have no padding bits.

That's my view of them. In order to steer clear of portability problems
I imagine an abstract C machine with the worst possible behaviour that I
think is still permitted by the standard. I've never written a program
that cares if the padding bits "stick" or not so this view of them is
pretty unlikely to matter to me but I can't be sure that they do retain
their settings, so until someone persuades me that objects hold their
last stored *representation* I'll stick with it.
 
S

Shao Miller

Shao Miller said:
Ben said:
[I will snip a lot because there seems to be only one issue here]
Ben Bacarisse wrote:
<snip>
At some level it doesn't matter either way.  Imagine an implementation
that adds 107 padding bits to every promoted int.  Since you can't
inspect these bits
That's really rather what I'm asking about.  I apologize if it's not
clear.  Please allow me to ask it differently: If we complement an
int' and store the result and inspect the object representation, are
we defined to discover that padding bits from the original have been
complemented in the stored result?  I doubt it, but am uncertain.
It is certain that it can't be true in general (if, say, any padding bit
set to 1 represents a trap, then ~0 can't invert the padding bits) so
why bother speculating about some other cases?
Aha.  Perhaps an example might help.

I don't think so.  An example of how unspecified behaviour might be
implemented does not address the question.  C certainly permits an
implementation to preserve or to manipulate the padding bits is almost
any way so there will be examples where useful things will happen.  In
general, you can't rely on what the padding bits end up holding but I
have no problem with an implementation that says a lot more.

If the wording of the Standard can reasonably be debated (reasonably
being subjective to participants and observers), then an example like
I gave could help to clarify my question, not to answer it. I'm
asking about the effect of unary '~' on padding bits because I'm
trying to understand what the Standard offers implementations and
programmers in regards to them. If we didn't write the Standard, then
we can either speculate on what reasoning led to the wording, or we
can find a definitive answer. Have we seen a definitive answer? If
not, my question can only be answered with advice for best practices
and speculation. My "snipped" example merely tries to help me to ask,
"Could the wording mean FOO and have stemmed from considerations such
as BAR?"
My argument that values don't have padding bits is just an abstract view
of how I think it helps to look at portable C which was, I think, the
original context.  Some implementations may be a lot more specific but
that's a lot less interesting.

If it ever turns out (which it mightn't) that padding bits are defined
to be complemented by unary '~', then that knowledge might be useful.
I genuinely appreciate your abstract view that you have shared. Where
you say that some implementations might be a lot more specific but a
lot less interesting, this I can disagree to. A portable program
which is capable of determining characteristics of the implementation/
environment through a battery of tests seems like it might be handy,
and this is part of the intentions behind the questions. Where the
Standard doesn't mandate that implementation-defined choices be
accessible in a portable fashion, how can we best find out about these
choices in efforts to produce portable programs? Mr. T. Rentsch's
integer limits code that he kindly shared recently are a really
enjoyable example.
If you want to read it that way.  I don't have any enthusiasm for an
argument about what an operand is
Ok.

-- its clear we don't agree about many
of the plain terms of the standard.

Why does this have to get personal? It doesn't. I don't know of any
terms at all that we disagree about. Perhaps I have communicated
poorly and my questions have been perceived as claims? If so, then I
apologize. Otherwise, I'd really rather agree than disagree. It
makes any discussion about our shared interest that much more
meaningful. :)
 But no matter, you are half way
there.  Because the standard says "(promoted) operand" rather than
"value" all you now need is some wording that lets you be convinced that
this representation has to get back into an object unchanged and you
will have the assurance you are looking for.

Whoa, whoa. I'm not looking for assurance that padding bits are
complemented. I'm inclined as you are to play it safe. I'm looking
for assurance that they either are defined to or are not defined to.
 Since padding bits in ints
(the usual promoted type for ~) are rare you won't have much trouble
with implementations that don't conform because they took another
reading of the standard.

Absolutely.


... ... ...

In the general case, yes.  In other words, your paraphrasing is the most
one be assured of.  Some implementations may be far more specific and
won't then fit with the view I've presented.  That, to me is the right
way round in that I am happier to permit specific exceptions to a
general rule that to have a specific rule that I have to keep reminding
myself does not apply in general.

Ok. Thanks. You have been asked for your interpretation and you have
given it along with good advice.
Why can't the padding in the struct change its setting between the copy
and the compare?

Why are you asking me when I'm asking you? I don't know the answer
and hoped that you or another reader might. I did suggest that
'unsigned char' has no padding bits, so for "last-stored value" to be
true, we must preserve all bits even if we are going to interpret them
at some point via a type which includes padding. What do you think?
If that was intended meaning, yes.  Do you know if that was the intent
or did the committee mean exactly what they wrote?

I do not know if that was the intent at all. What do you think?
Maybe someone who knows the author's/authors' intentions could help to
answer?
Since I have no interest in writing a program where the distinction
matters, I am happy with either meaning; and if I ever have to write
such a program I'll take the interpretation that gives me the least
guarantees just to be on the safe side.

Absolutely. :)
That's my view of them.  In order to steer clear of portability problems
I imagine an abstract C machine with the worst possible behaviour that I
think is still permitted by the standard.  I've never written a program
that cares if the padding bits "stick" or not so this view of them is
pretty unlikely to matter to me but I can't be sure that they do retain
their settings, so until someone persuades me that objects hold their
last stored *representation* I'll stick with it.

Ok. So this particular scenario of copying object representations and
comparing has not been particularly practical, in your experience.
 
S

Shao Miller

Applying the ~ operator to an operand that produces such a value, which is
explicitly undefined behavior.

Excellent, as always. Then I can add to a list of exceptional
conditions and take it that we have to be extra careful about, say,
'~32767' for a 16-bit 'int' with sign-and-magnitude representation,
since we might get undefined behaviour. Fair enough! :) Thank you.
 
S

Shao Miller

No.  *All* operators operate on values, not object representations, and
padding bits (by definition) are not part of the value.  Their settings
are always unspecified.

Very well. This is completely consistent with Ben's notion of an
abstract mathematical value without representation. Quick question:
After a copy of something including unspecified padding bits via
'unsigned char', can we expect that the bits in the copy match the
bits of the original if we compare via 'unsigned char'? Or does the
type of the original allow for the padding bits in the copy to be
theoretically random even during the copy; even if byte comparison is
the very first thing we do before using the copy via the type of the
original? Thank you.
 
L

lawrence.jones

Ben Bacarisse said:
Why can't the padding in the struct change its setting between the copy
and the compare?

Because the bytes that compose the struct are themselves objects (that
don't have padding bits) and thus subject to the "objects retain their
last stored value" guarantee.
 
S

Shao Miller

Shao said:
Very well. This is completely consistent with Ben's notion of an
abstract mathematical value without representation. Quick question:
After a copy of something including unspecified padding bits via
'unsigned char', can we expect that the bits in the copy match the
bits of the original if we compare via 'unsigned char'? Or does the
type of the original allow for the padding bits in the copy to be
theoretically random even during the copy; even if byte comparison is
the very first thing we do before using the copy via the type of the
original? Thank you.

I see that you answered this quick question in another post. You stated
that "...the bytes that compose the struct are themselves objects (that
don't have padding bits) and thus...retain their last stored value..."
(please forgive the exclusions).

In this case, could "last-stored object representation" lead to this
conclusion perhaps more directly for a reader? Because the C1X draft
has "come to the rescue" three times already in my recollection, I did
check it out before asking. :)

Also, I think it might be worth noting that I think your "*All*" might
require the context of arithmetic operators... 'sizeof' doesn't strike
me as operating on a value, neither does a redundant cast to 'void', nor
a ternary conditional operator with two void expressions as second and
third operands, nor a comma operator with void expressions as operands,
nor 'alignof' in C1X. I've no idea if '_Generic()' in C1X should be
called a proper operator or not.

But anyway, it's good to know that unary '~' is not defined to have any
influence on padding bits anywhere, as per the majority of responses
here... I'll just wish that it was a little more directly evident...
C1X 6.5p4 describes values with types and representations, and that
includes padding bits, to me.

Thanks again.
 
B

Ben Bacarisse

Shao Miller said:
Shao Miller said:
Ben Bacarisse wrote:
[I will snip a lot because there seems to be only one issue here]
Shao Miller <[email protected]> writes:
Ben Bacarisse wrote:
<snip>
At some level it doesn't matter either way.  Imagine an implementation
that adds 107 padding bits to every promoted int.  Since you can't
inspect these bits
That's really rather what I'm asking about.  I apologize if it's not
clear.  Please allow me to ask it differently: If we complement an
int' and store the result and inspect the object representation, are
we defined to discover that padding bits from the original have been
complemented in the stored result?  I doubt it, but am uncertain.
It is certain that it can't be true in general (if, say, any padding bit
set to 1 represents a trap, then ~0 can't invert the padding bits) so
why bother speculating about some other cases?
Aha.  Perhaps an example might help.

I don't think so.  An example of how unspecified behaviour might be
implemented does not address the question.  C certainly permits an
implementation to preserve or to manipulate the padding bits is almost
any way so there will be examples where useful things will happen.  In
general, you can't rely on what the padding bits end up holding but I
have no problem with an implementation that says a lot more.

If the wording of the Standard can reasonably be debated (reasonably
being subjective to participants and observers), then an example like
I gave could help to clarify my question, not to answer it.

I don't think I've misunderstood your question. The example certainly
did not make me look at the question in a new light. Maybe I missed the
point.
I'm
asking about the effect of unary '~' on padding bits because I'm
trying to understand what the Standard offers implementations and
programmers in regards to them. If we didn't write the Standard, then
we can either speculate on what reasoning led to the wording, or we
can find a definitive answer. Have we seen a definitive answer?

There is no "we" in this regard. You have to answer for yourself.
Presumably nothing anyone has said has so far seemed definitive.
If
not, my question can only be answered with advice for best practices
and speculation. My "snipped" example merely tries to help me to ask,
"Could the wording mean FOO and have stemmed from considerations such
as BAR?"

Had you asked that, I would have had a go at answering it, but it seemed
to be simply a case where parity was preserved under complement. I
can't see how that sheds any light on the matter. Almost everything to
about padding bits is unspecified so as to permit this along with dozens
of other schemes.
If it ever turns out (which it mightn't) that padding bits are defined
to be complemented by unary '~', then that knowledge might be useful.
I genuinely appreciate your abstract view that you have shared. Where
you say that some implementations might be a lot more specific but a
lot less interesting, this I can disagree to. A portable program
which is capable of determining characteristics of the implementation/
environment through a battery of tests seems like it might be handy,
and this is part of the intentions behind the questions.

Programming is ultimate a practical endeavour -- please give an example.
What might you like to find out with a portable program? How might the
answer help or be otherwise useful? With a real practical goal, you
might find more people willing to join in.
Where the
Standard doesn't mandate that implementation-defined choices be
accessible in a portable fashion, how can we best find out about these
choices in efforts to produce portable programs? Mr. T. Rentsch's
integer limits code that he kindly shared recently are a really
enjoyable example.

Agreed. What similarly practical problem has led to this question about
padding bits and the ~ operator?
Why does this have to get personal?

What's personal about that? I may be wrong, but it is not a personal
remark.
It doesn't. I don't know of any
terms at all that we disagree about.

Operand, value and result spring to mind. Maybe we are now in agreement
about "result" but I don't recall any clear resolution. You would not
say "6.5.3.3p4 says 'operand' rather than 'value'" if we agreed on those
two terms. The last time a similar case cropped up (whether a result
can be a type devoid of any associated value) it went on far longer that
it should have. I intend to do better in future!
Perhaps I have communicated
poorly and my questions have been perceived as claims? If so, then I
apologize. Otherwise, I'd really rather agree than disagree. It
makes any discussion about our shared interest that much more
meaningful. :)


Whoa, whoa. I'm not looking for assurance that padding bits are
complemented. I'm inclined as you are to play it safe. I'm looking
for assurance that they either are defined to or are not defined to.

Let's put aside the issue of whether the padding bits are even there in
the promoted result and assume that they are (I don't agree but lets go
there for the moment). I gave an example where they must not be
inverted by the ~ operator -- where any padding bit other than 0 is a
trap representation. From this I think one must conclude that there
could not a requirement that they be complemented.

Why are you asking me when I'm asking you?

Because I disagreed and wanted to point to what I thought was the key
issue, but I am not so sure anymore.

I think you are right if there is access via a character-typed lvalue
expression. That's not always the case in the copying scenario you
describe but since the smallest change to the program would require the
whole structure to be stable it seems inconceivable that any
implementation would distinguish between the two situations.

There are things to worry about, there are things not to worry about and
then there is this!

<snip>
 
B

Ben Bacarisse

Because the bytes that compose the struct are themselves objects (that
don't have padding bits) and thus subject to the "objects retain their
last stored value" guarantee.

That surprises me (but only a little) because of 6.2.6.1 p6. These are
component objects that retain their last stored value but which may
change value when other (possibly distant) parts of the larger object
have *their* stored value changed.

BTW, I now think my original claim is wrong but I am still a little
puzzled by what constitutes the "last stored value" for a padding byte
in a struct.
 
S

Shao Miller

Ben said:
Shao Miller said:
Ben Bacarisse wrote:
[I will snip a lot because there seems to be only one issue here]
Ben Bacarisse wrote:
<snip>
... ... ...
I don't think I've misunderstood your question. The example certainly
did not make me look at the question in a new light. Maybe I missed the
point.

If you did, that's a failure on my part to communicate.
There is no "we" in this regard. You have to answer for yourself.
Presumably nothing anyone has said has so far seemed definitive.

I'm thinking that something along the lines of:

A: Note section BAZ, point WHEE: "It is unspecified whether computations
of a value affect padding bits or not."

might be a definitive answer. I'd hope that "we" could agree to such,
if A piped-in with that.
Had you asked that, I would have had a go at answering it, but it seemed
to be simply a case where parity was preserved under complement. I
can't see how that sheds any light on the matter. Almost everything to
about padding bits is unspecified so as to permit this along with dozens
of other schemes.

Thanks. That makes sense. Then perhaps the authors did not intend to
limit the uses of padding bits and did not intend to constrain integer
representations beyond the three value formats in signed representations.
Programming is ultimate a practical endeavour -- please give an example.
What might you like to find out with a portable program? How might the
answer help or be otherwise useful? With a real practical goal, you
might find more people willing to join in.

Good point and I will keep that in mind. Perhaps you are correct and
more people will be inclined to discuss possibly practical code rather
than Standard theory. Very well.
Agreed. What similarly practical problem has led to this question about
padding bits and the ~ operator?

Reporting to a programmer which trap representations are suspected for
the environment. If and only if padding bits are guaranteed to
complement, this limits what padding bits can be used for, and as we
compare object representations to known representations, we needn't
consider known representations where padding bits do not complement;
they wouldn't be allowed for conformance.
What's personal about that? I may be wrong, but it is not a personal
remark.

I misunderstood, then. Sorry.
Operand, value and result spring to mind. Maybe we are now in agreement
about "result" but I don't recall any clear resolution. You would not
say "6.5.3.3p4 says 'operand' rather than 'value'" if we agreed on those
two terms. The last time a similar case cropped up (whether a result
can be a type devoid of any associated value) it went on far longer that
it should have. I intend to do better in future!

"Operand" is 6.4.6p2. "Value" is 3.17p1 in 'n1256.pdf' and 3.19p1 in
C1X. I am not familiar with a C Standard definition for "result", not
sure one is possible, and not sure one is needed; a dictionary
definition might suffice. I think we can reasonably understand "result"
to be an accumulation of defined properties and predicate-truths.

But you're absolutely right: Let's not go there. :)
Let's put aside the issue of whether the padding bits are even there in
the promoted result and assume that they are (I don't agree but lets go
there for the moment). I gave an example where they must not be
inverted by the ~ operator -- where any padding bit other than 0 is a
trap representation. From this I think one must conclude that there
could not a requirement that they be complemented.

I agree with this. It's certainly one way or the other: Either the
Standard constrains what padding bits can be used for (beyond that we
know they contribute to neither sign nor value) or it doesn't. If it
doesn't, then the situation you describe would require that unary '~'
does not complement all bits in a result.
... ... ...
... ... ...
There are things to worry about, there are things not to worry about and
then there is this!

Ok.
 
B

Ben Bacarisse

Shao Miller said:
Ben said:
Shao Miller <[email protected]> writes:
[...] My "snipped" example merely tries to help me to ask,
"Could the wording mean FOO and have stemmed from considerations such
as BAR?"

Had you asked that, I would have had a go at answering it, but it seemed
to be simply a case where parity was preserved under complement. I
can't see how that sheds any light on the matter. Almost everything to
about padding bits is unspecified so as to permit this along with dozens
of other schemes.

Thanks. That makes sense. Then perhaps the authors did not intend to
limit the uses of padding bits and did not intend to constrain integer
representations beyond the three value formats in signed
representations.

I'd agree if you dropped the "Then...". Perhaps the authors intended
all sorts of other things (it's always possible) but in no way does your
second suggestion follow from your agreement with me.

I agree with this. It's certainly one way or the other: Either the
Standard constrains what padding bits can be used for (beyond that we
know they contribute to neither sign nor value) or it doesn't. If it
doesn't, then the situation you describe would require that unary '~'
does not complement all bits in a result.

Odd. You agree and then write something different. I am glad you agree
but I am not 100% sure what you agree with.

<snip>
 
S

Shao Miller

Ben said:
Shao Miller said:
Ben said:
Shao Miller <[email protected]> writes:
[...] My "snipped" example merely tries to help me to ask,
"Could the wording mean FOO and have stemmed from considerations such
as BAR?"
Had you asked that, I would have had a go at answering it, but it seemed
to be simply a case where parity was preserved under complement. I
can't see how that sheds any light on the matter. Almost everything to
about padding bits is unspecified so as to permit this along with dozens
of other schemes.
Thanks. That makes sense. Then perhaps the authors did not intend to
limit the uses of padding bits and did not intend to constrain integer
representations beyond the three value formats in signed
representations.

I'd agree if you dropped the "Then...". Perhaps the authors intended
all sorts of other things (it's always possible) but in no way does your
second suggestion follow from your agreement with me.

"Almost everything to [do with] padding bits is unspecified so as to
permit this along with dozens of other schemes." <-> "Then perhaps the
authors did not intend to limit the uses of padding bits..." Permit.
Did not intend to limit.
Odd. You agree and then write something different. I am glad you agree
but I am not 100% sure what you agree with.

It's simple. In my first response to Mr. E. Sosman, I noted this very
example but didn't completely reference it. In 'n1256.pdf', the example
is present in footnotes 44 and 45.

"I did see an example in the C1X draft where a padding bit might be a
parity bit. My impression was that the bit _might_ be complemented
during the bitwise '~', but only as a matter of co-incidence, and not
because '~' is defined to complement padding bits. Would you agree to
that?"

As Mr. Sosman said, if we accept that 6.2.6.2's padding bits being
"unspecified" takes precedence above anything else (such as an operand
value having a type and the operand beyond its value being subject to a
type representation including padding bits), then that's that. 3.17.3p1
"...imposes no requirements..." (other than a bit being either one or zero).

Speaking of which, I think it's important to note the relativity of
unspecified values for padding bits. They are unspecified relative to
value and sign bits in an object interpreted as having an integer type
which includes padding bits. I don't think that they are unspecified so
far as to change between reads without intervening stores (which for
'volatile' mightn't be explicit in the program). I think any other
treatment would be chaotic...

Which is why I asked if "last-stored object representation" might be
more accurate for 6.2.4p2. Since "value" implies type[3.17p1], it could
be interpreted as objects having some set type. But as always, I could
be wrong. I would find it quite surprising if copying an 'int' via
'unsigned char[]' followed immediately by an 'unsigned char[]'
comparison of the original and the copy yielded differences because
'int' was somehow secretly the "real type" of the object. Heheh.

Padding bits might be unspecified, but they're not always padding bits. :)
 
S

Shao Miller

Ben said:
That surprises me (but only a little) because of 6.2.6.1 p6. These are
component objects that retain their last stored value but which may
change value when other (possibly distant) parts of the larger object
have *their* stored value changed.

The way I try to make sense of it is that C only has one "real" type for
objects: 'unsigned char' (an unsung character type). For
non-addressable storage (like 'register'), perhaps this doesn't apply
quite as much. I pretend that any other type is "projected". So
"last-stored value" to me implies some "real" type, which then to me
means "as unsigned char".

The wording of 6.2.6.1p6 could possibly mean two things:

"When a value with structure or union type is stored into an object with
that type..."

or it could mean:

"When a value with any type is stored into a member of an object with
structure or union type..."

I prefer the former interpretation, as it gives me an "all-at-once"
notion for a contiguous range of storage; some of it being unspecified
and some of it not. Thus the components are being "stored-to" and the
previously stored value is lost.
BTW, I now think my original claim is wrong but I am still a little
puzzled by what constitutes the "last stored value" for a padding byte
in a struct.

It was a question until you typed it was a claim. ;)
 
B

Ben Bacarisse

Shao Miller said:
The way I try to make sense of it is that C only has one "real" type
for objects: 'unsigned char' (an unsung character type). For
non-addressable storage (like 'register'), perhaps this doesn't apply
quite as much. I pretend that any other type is "projected". So
"last-stored value" to me implies some "real" type, which then to me
means "as unsigned char".

That's not helping to explain this curiosity to me.
The wording of 6.2.6.1p6 could possibly mean two things:

"When a value with structure or union type is stored into an object
with that type..."

or it could mean:

"When a value with any type is stored into a member of an object with
structure or union type..."

I prefer the former interpretation, as it gives me an "all-at-once"
notion for a contiguous range of storage; some of it being unspecified
and some of it not. Thus the components are being "stored-to" and the
previously stored value is lost.

I don't see how you can choose one interpretation over the other when
the wording of the paragraph seem to me to include both cases. I am not
certain you mean the two cases that 6.2.6.1 p6 covers(because you've
changed the wording slightly) but I think your intent is somehow to
ignore or sideline the "including in a member object" wording.

I read that paragraph as meaning that after:

struct { unsigned char x[3]; } eg; /* assume one padding byte */
memset(&eg, 0, sizeof eg);
eg.x[0] = ' ';

the padding byte may no longer be 0.

This is slightly at odds with Lawrence Jones's statements that the
padding bytes are objects in their own right and thus keep their "last
stored value" like any other. I say "slightly at odds" because is is
possible that what constitutes the "last store" is not a simple and
obvious matter.

[Aside: Despite the esoteric example, I do know why that wording is
there -- it is there to cover the cases where the padding is needed for
efficient reads and stores. Short ints might be padded so as to be able
to load and store in larger chunks. This is very common with bit-fields.
However, the wording means that nothing much can be assumed about the
padding bytes even when there is no practical reason to worry.]

<snip>
 
S

Shao Miller

Ben said:
Shao Miller said:
Ben said:
Ben Bacarisse wrote:
<snip>
[...] My "snipped" example merely tries to help me to ask,
"Could the wording mean FOO and have stemmed from considerations such
as BAR?"
Had you asked that, I would have had a go at answering it, but it seemed
to be simply a case where parity was preserved under complement. I
can't see how that sheds any light on the matter. Almost everything to
about padding bits is unspecified so as to permit this along with dozens
of other schemes.

Thanks. That makes sense. Then perhaps the authors did not intend to
limit the uses of padding bits and did not intend to constrain integer
representations beyond the three value formats in signed
representations.
I'd agree if you dropped the "Then...". Perhaps the authors intended
all sorts of other things (it's always possible) but in no way does your
second suggestion follow from your agreement with me.
"Almost everything to [do with] padding bits is unspecified so as to
permit this along with dozens of other schemes." <-> "Then perhaps the
authors did not intend to limit the uses of padding bits..." Permit.
Did not intend to limit.

You posted an example of a scheme for using padding bits. I said this
and dozens of other schemes are permitted. Where is the connection to
the three value formats in signed representations?

My impression is that the Standard has some requirements for padding bits:
1. They are distinct from the "value" and "sign" groups of bits in a
representation of a value with integer type.
2. They are optional.
3. Each one is a unit of data storage having one of two possible values.
4. They may optionally contribute to a trap representation.
5. They may optionally contribute to alternative representations of the
same integer value.
6. They are not padding bits in the context of a representation of a
value with character type.
7. They cannot contribute to a trap representation for a value with
integer type from the result of an arithmetic operation.
8. All other properties are not Standard requirements.

The connection is: Integer type representations are constrained by the
Standard. Value bits are part of integer representations. Value bits
are constrained to one of the three representations. My impression is
that padding bits are constrained as above. Now please take my sentence:

"Then perhaps the authors did not intend to limit the uses of padding
bits and did not intend to constrain integer representations beyond the
three value formats in signed representations."

I was commenting on the possibility that the relevant authors of the
relevant portions of the Standard did not intend to constrain integer
representations to exclude potential uses of padding bits, which is
congruent with your statement:

"Almost everything to [do with] padding bits is unspecified so as to
permit this along with dozens of other schemes."
... ... ...
I am glad you think it's simple. I still have no idea what you now
agree with and/or don't agree with. If, in some other discussion, I say
that we disagree please bear in mind it may simply be that I have lost
track.

Great. I agree that the parity bit example in footnotes 44 and 45 has
relevance to the discussion. They are non-normative, but are intended
to follow from normative text, according to Mr. L. Jones.

There are padding bit usage schemes (only one such described in a
previous post) to meet my suggested padding bit requirement #7 above
while allowing for padding bits to be directly operated upon by
arithmetic operators, and such schemes would then be the only schemes
which padding bits could be used for. So #7 can constrain padding bits,
or #8 can take precedence and #7 follows from other definitions.

Since the Standard constrains value and sign bits, it didn't seem 100%
impossible that the Standard might also attempt to constrain the uses of
padding bits while defining that a bitwise operator such as unary '~'
work directly on all bits; after all, 'unsigned char' works with all
bits, one byte at a time.

I'm happy to simply say "Nope." :) (Except that padding bit uses are
more wild than they might otherwise be, but oh well.)
 
S

Shao Miller

Shao said:
Ben said:
... ... ...
This is slightly at odds with Lawrence Jones's statements that the
padding bytes are objects in their own right and thus keep their "last
stored value" like any other. I say "slightly at odds" because is is
possible that what constitutes the "last store" is not a simple and
obvious matter.

... ... ...

Ok. Maybe we spread parity throughout the padding of a 'struct', too.
That makes for an excellent new test!

#include <string.h>

int main(void) {
struct three {
unsigned char ca[3];
};
union {
unsigned char ca[sizeof (struct three) + 10];
struct {
union {
struct three alignment;
int dummy;
} dummy;
} dummy;
} foo;
unsigned char *uh_oh;

memset(foo.ca, 'A', sizeof foo.ca);
uh_oh = ((struct three *)&foo)->ca + 2;
*uh_oh = 'B';
/* foo.ca could be AAB???..etc..AAAAAAAAAA */
return 0;
}

Or perhaps even better!:

#include <string.h>

int main(void) {
struct three {
unsigned char ca[3];
};
union {
struct {
struct three alignment;
int dummy;
} with_int;
struct {
struct three alignment;
double dummy;
} with_double;
} foo;
unsigned char *uh_oh;

uh_oh = ((struct three *)&foo)->ca + 2;
/*
* Does 'uh_oh' point to:
* foo.with_int.aligment.ca + 2
* Or:
* foo.with_double.alignment.ca + 2
*/
*uh_oh = 'B';
/*
* Which padding bits are unspecified? Those in:
* foo.with_int.alignment ?
* foo.with_int ?
* foo.with_double.alignment ?
* foo.with_double ?
*/
return 0;
}
 

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
474,082
Messages
2,570,589
Members
47,212
Latest member
JaydenBail

Latest Threads

Top