[Openswan dev] libosw (fwd)
D. Hugh Redelmeier
hugh at mimosa.com
Tue Sep 13 11:57:43 EDT 2011
| From: Michael Richardson <mcr at sandelman.ca>
| I'm using libopenswan (initsubnet, etc.) in another project.
| We just discovered that gcc-4.5 is even more pedantic.
|
| initsubnet.c: In function 'initsubnet':
| initsubnet.c:38:2: error: new qualifiers in middle of multi-level non-const cast are unsafe
|
| referring to:
|
| n = addrbytesptr(&dst->addr, (const unsigned char **)&p);
That's odd. I don't think that the new qualifier is in the middle --
it's on the lowest level.
C's const is too simplistic. One wants to write functions where the
qualifications of some arguments or results is a function of the
qualifications of some other arguments or results. That cannot be
expressed.
The classic example is strchr. The definition says:
char *strchr(const char *s, int c);
BUT the correct (inexpressible) qualification of the first arg is
const-optional and the correct qualification of the result is
same-constness-as-s. So that is a fudge.
If C allowed overloading, you'd have two functions:
char *strchr(char *s, int c);
const char *strchr(const char *s, int c);
with one implementation (because the implementation doesn't actually
depend on the constness).
addrbytesptr wants the same thing (constness **dstp should be the same
as the constness of *src) but has been coded in the pure way: with
both const.
Here's what I GUESS would pass any purity test. This replaces the call
to addrbytesptr in initsubnet.
{
const unsigned char *q;
n = addrbytesptr(&dst->addr, &q);
p = (unsigned char *) (void *) &dst->addr;
p += (const unsigned char *)q - p;
}
A simpler but sloppy change would be to remove the const from the
declaration of dstp in addrbytesptr. I expect that the compiler would
whine. You could find out how glibc gets around this for strchr (I'm
too lazy at the moment).
| the net suggests that maybe it should be:
| n = addrbytesptr(&dst->addr, (const unsigned char *const *)&p);
|
| but, actually that's not right, the function is going to modify the
| thing pointed to, but not the pointer itself.
Agreed. A "middle" const qualification isn't in play.
Heck -- maybe it's a gcc bug. Try gcc 4.6.
| google found one hit for this error on the openswan list a year ago, but
| nobody appears to have solved this, unless I missed something.
I don't subscribe to the users list and the archive seems to be down
at the moment.
| Do you understand this?
The semantics of const are (is?) slippery.
It doesn't mean "this thing isn't going to change".
I think that it really means "nobody will write to this thing using an
L-value derived from this value or referent". That means that casting
away const does not get rid of the obligation. But casting to const
does create an obligation! Note: I haven't read the standard on this
in years so my internalization is possibly wrong (likely more
consistent).
| I think that I need to write "non-const", but I
| didn't think I could do that.
Not writing "const" means "non-const".
More information about the Dev
mailing list