Re: You're appointed as Portability Advisor
- From: Kaz Kylheku <kkylheku@xxxxxxxxx>
- Date: Thu, 14 Feb 2008 17:53:57 -0800 (PST)
On Feb 14, 4:05 pm, "Tomás Ó hÉilidhe" <t...@xxxxxxxxxxx> wrote:
We frequently discuss portability here. I think most of us would agree
that for a program to be portable, the following two criteria must be
met:
1) None of its behaviour is undefined by the Standard.
Depends on which standard you choose. According to the C one,
#include <fcntl.h>
is undefined behavior. As a portability advisor to real people working
in real trenches, you have to allow for extensions.
What we want to aim for is not avoiding extensions, but rather /
knowing/ what the documented extensions are and using them
deliberately.
You're sitting there 100% aware that the Standard explicitly forbids you
to write to member A of a union and then read from member B, but how
much do you care?
You can write to member A and read through member B, if member B is a
character type that treats the thing as an array of bytes.
I would simply remove the member "entire" from the union, and change
it to a struct. Then see what breaks when you recompile the program,
and fix those occurences. The struct itself gives you the entire
thing. You can define objects of that struct type, pass them to
functions, return them, assign them, etc.
Later on in the code, you come to:
double tangents[5];
...
double *p = tangents;
double const *const pend = *(&tangents + 1);
Again, you look at this code and you think to yourself this really is
quite a neat way of achieving what he wants.
This can simply be edited to:
double *pend = tangents + sizeof tangents / sizeof tangents[0];
Or maybe the size should be a manifest constant somewhere:
double tangents[vector_size];
const double *const pend = &tangents[vector_size];
*(&tangents + 1) stops being neat once you get out of programming
puberty. Stuff like that looked neat when I was learning C for the
first time. It's not neat; it's just cryptic B. S.
99% of the C programmers out there have probably never seen an array
type manipulated as an array type---addresses being taken to make
pointer-to-array types, etc. Their heads will do a double, triple or
even quadruple ``take'' when they see that expression.
Are you, as the Portability Advisor, going to reject this code?
Of course! There is no need for it to be doing what it's trying to do
by that means. There is no need to rely on an undocumented extension
of behavior to get the desired effect.
What I'm trying to get across is, that, while we may discuss in black
and white what the Standard permits and what it forbids... are we really
going to be so obtuse as to reject this code in the real world?
Absolutely. At /least/ that obtuse, if not way more.
And don't forget that we have a $500K salary as portability advisor,
and so we must scramble for every little thing that can add a line or
two to our weekly status report, and that can make us look very sharp
and justify our job position in the eyes of senior management.
There is always that!
Are we
really going to reject some code for a reason that we see as stupidly
restrictive in the language's definition?
It's not stupidly restrictive when you can rewrite the expression in a
way that will not surprise most of the programmers out there, and that
doesn't break any rules.
A restriction is something that actually gets in your way; it makes
something impossible to do at all, or maybe only with an
unsatisfactory workaround.
Perhaps it might be useful to point out what exactly can go wrong when
we're treading on a particular rule. In both these cases I've mentioned,
I don't think anything can go wrong, not naturally anyway. What _can_
cause problems tho is aspects of the compiler:
1) Over-zealous with its optimisation
2) Deliberately putting in checks (such as terminating the program when
it thinks you're going to access memory out-of-bounds).
There is
3) Wasting people's time when they have to scratch their heads about
what *(&array + 1) actually means and whether or not it's right.
Should we have a webpage that lists the common coding techniques that
skilled programmers use, but which are officially forbidden or "a grey
area" in the Standard?
Two such rules I myself would put on the list are:
1) Accessing different union members
Definitely not; count me out from your webpage.
The purpose of a union is to save space in implementing polymorphism.
If you store member X, you read member X.
Type punning is inherently nonportable. It's not enough to say that
type punning is allowed through members of a union, but undefined
elsewhere. To define its behavior, it's not enough to simply permit
some action. The outcome of the action must be specified. And you
cannot do that because it's totally nonportable.
At best you could say that if a member Y is accessed after member X is
stored, then there shall be no aliasing problem: Y will be
reconstituted out of the bits that were actually stored through X.
However, that's not anywhere nearly complete a definition of behavior
to be practically useful. That kind of thing belongs in the
architecture-specific pages of a compiler reference manual, not in the
language.
2) De-referencing a pointer to an array
But that is allowed. I think you mean, dereferencing a pointer to one
element past the end of an array-of-array object, where it's not
pointing to any array.
I tend to agree with this.
That is to say, the address-of operator could have some additional
semantic rules, along these lines:
When the operand of the address-of operator is a pointer-
dereferencing
expression based on the unary * operator, the two operators
effectively
cancel each other out, so that &*(E) is equivalent to (E), provided
that (E) is valid pointer: either a pointer to an object, a null
pointer, or a pointer one element past the end of an array object.
I can't think of a way of allowing (E)->member or (*(E)).member to be
defined when E is null, or otherwise valid but not pointing to an
object. Is there a use for this other than implementing offsetof,
which is already done for you?
.
- References:
- You're appointed as Portability Advisor
- From: Tomás Ó hÉilidhe
- You're appointed as Portability Advisor
- Prev by Date: Re: You're appointed as Portability Advisor
- Next by Date: Re: You're appointed as Portability Advisor
- Previous by thread: Re: You're appointed as Portability Advisor
- Next by thread: Re: You're appointed as Portability Advisor
- Index(es):
Relevant Pages
|