T
Tomás Ó hÉilidhe
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.
2) Any behaviour which is unspecified or implementation-defined does not
interfer with the intended behaviour of the program.
When laid out in black and white like that, these rules are quite clear.
However, let's consider this: Let's say you're appointed as the
Portability Advisor for a multi-national company that makes billions of
dollar each year. They pay you $500,000 a year, they have you working 30
hours a week and they give you 60 days paid holiday leave per year. They
don't block newsgroups, and their firewall only blocks the most
offensive of sites. They even get a Santa for the kids at the Christmas
party.
Your job is to screen the code that other programmers in the company
write. Every couple of days there's a fresh upload of code to the
network drive, and your job is to scan thru the code and point out and
alter anything that's not portable. Of course tho, you're given a
context in which to judge the code, for instance:
a) This code must run on everything from a hedge-trimmer to an iPod, to
a Playstation 3,
b) This code must run on all the well-known Desktop PC's
Depending on the context, you judge some code harsher than others. For
instance, in context B, you might allow assumptions that there's an even
number of bits in a byte, also that integer types don't contain padding.
While in context A, you might fire that code right back if you see such
assumptions.
So... it's Thursday morning, you sit down to your desk with a hot cup of
tea and a fig-roll bar, you check your mail. You surf the web for a
couple of minutes, perhaps check the latest scores in the election, or
look up where you can get a new electric-window switch for your car
since it mysteriously stopped working this morning.
You get down to it. You open up the network drive and navigate to James
Weir's source file. Its context is "run on anything". You're looking
thru it and you come to the following section of code:
typedef union ConfigFlags {
unsigned entire; /* Write to all bytes
char unsigned bytes[sizeof(unsigned)]; at once or access
} ConfigFlags; them individually
*/
int IsRemoteAdminEnabled(ConfigFlags const cf)
{
return cf.bytes[3] & 0x3u;
}
You look at this code and you think, "Hmm, this chap plans to write to
'entire' and then subsequently read individual bytes by using the
'bytes' member of the structure". You have a second suspicion that
perhaps James might have made assumptions about the size of "unsigned",
but inspecting the code you find that he hasn't.
Now, the question is, in the real world, at 10:13am on a sunny Thursday
morning, sitting at your desk with a hot cup of tea, munching away on a
fig-roll bar getting small crumbs between the keys on the keyboard, are
you really going to reject this code?
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?
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. Again, you know that the
Standard in all its marvelous rigidity doesn't want you to dereference
that pointer, but are you bothered? Are you, as the Portability Advisor,
going to reject this code?
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? Are we
really going to reject some code for a reason that we see as stupidly
restrictive in the language's definition?
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).
The first thought I think comes to everyone's mind when we're talking
about these unnecessarily rigid rules, is that the Standard just needs
to be neatly amended. But, of course, it's C we're talking about, where
the current standard is from 1989 and where still not too many people
are paying attention to the 1999 standard that came out nine years ago.
So, I wonder, what can we do? If there was a consenus between many of
the world's most skilled and experienced C programmers that a certain
rule in the Standard were unnecessarily rigid, would it not be worth the
compiler vendors' while to listen? Here at comp.lang.c, there are,
without exageration, some of the world's best C programmers. Instead of
contacting each and every compiler vendor to let them know that we'd
prefer to optimise-away assignments to union members, would it be
convenient, both for the programmers and the compiler vendors, to have a
single place to go to to read what the world's best programmers think?
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
2) De-referencing a pointer to an array
that for a program to be portable, the following two criteria must be
met:
1) None of its behaviour is undefined by the Standard.
2) Any behaviour which is unspecified or implementation-defined does not
interfer with the intended behaviour of the program.
When laid out in black and white like that, these rules are quite clear.
However, let's consider this: Let's say you're appointed as the
Portability Advisor for a multi-national company that makes billions of
dollar each year. They pay you $500,000 a year, they have you working 30
hours a week and they give you 60 days paid holiday leave per year. They
don't block newsgroups, and their firewall only blocks the most
offensive of sites. They even get a Santa for the kids at the Christmas
party.
Your job is to screen the code that other programmers in the company
write. Every couple of days there's a fresh upload of code to the
network drive, and your job is to scan thru the code and point out and
alter anything that's not portable. Of course tho, you're given a
context in which to judge the code, for instance:
a) This code must run on everything from a hedge-trimmer to an iPod, to
a Playstation 3,
b) This code must run on all the well-known Desktop PC's
Depending on the context, you judge some code harsher than others. For
instance, in context B, you might allow assumptions that there's an even
number of bits in a byte, also that integer types don't contain padding.
While in context A, you might fire that code right back if you see such
assumptions.
So... it's Thursday morning, you sit down to your desk with a hot cup of
tea and a fig-roll bar, you check your mail. You surf the web for a
couple of minutes, perhaps check the latest scores in the election, or
look up where you can get a new electric-window switch for your car
since it mysteriously stopped working this morning.
You get down to it. You open up the network drive and navigate to James
Weir's source file. Its context is "run on anything". You're looking
thru it and you come to the following section of code:
typedef union ConfigFlags {
unsigned entire; /* Write to all bytes
char unsigned bytes[sizeof(unsigned)]; at once or access
} ConfigFlags; them individually
*/
int IsRemoteAdminEnabled(ConfigFlags const cf)
{
return cf.bytes[3] & 0x3u;
}
You look at this code and you think, "Hmm, this chap plans to write to
'entire' and then subsequently read individual bytes by using the
'bytes' member of the structure". You have a second suspicion that
perhaps James might have made assumptions about the size of "unsigned",
but inspecting the code you find that he hasn't.
Now, the question is, in the real world, at 10:13am on a sunny Thursday
morning, sitting at your desk with a hot cup of tea, munching away on a
fig-roll bar getting small crumbs between the keys on the keyboard, are
you really going to reject this code?
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?
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. Again, you know that the
Standard in all its marvelous rigidity doesn't want you to dereference
that pointer, but are you bothered? Are you, as the Portability Advisor,
going to reject this code?
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? Are we
really going to reject some code for a reason that we see as stupidly
restrictive in the language's definition?
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).
The first thought I think comes to everyone's mind when we're talking
about these unnecessarily rigid rules, is that the Standard just needs
to be neatly amended. But, of course, it's C we're talking about, where
the current standard is from 1989 and where still not too many people
are paying attention to the 1999 standard that came out nine years ago.
So, I wonder, what can we do? If there was a consenus between many of
the world's most skilled and experienced C programmers that a certain
rule in the Standard were unnecessarily rigid, would it not be worth the
compiler vendors' while to listen? Here at comp.lang.c, there are,
without exageration, some of the world's best C programmers. Instead of
contacting each and every compiler vendor to let them know that we'd
prefer to optimise-away assignments to union members, would it be
convenient, both for the programmers and the compiler vendors, to have a
single place to go to to read what the world's best programmers think?
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
2) De-referencing a pointer to an array