Bug in wimp.h
Chris Rutter
chris at willow.armlinux.org
Thu Aug 24 12:53:00 BST 2000
On Thu, 24 Aug 2000, David Bryan wrote:
> Yes, I thought Chris was right. From K&R Second Ed.,
>
> The purpose of const is to announce objects that may be placed
> in read-only memory, and perhaps to increase opportunities for
> optimization.
Well, in all fairness, `const' being a rather subtle beast, there /is/
a chance that K&R2 is inaccurate w.r.t. ANSI C89.
> I thought that compilers tended not to perform such optimisation,
> because such pointer optimisation can be hard to get right, and
> doesn't yield much improvement.
Yes, absolutely; I think most backends tend to have such tight
restrictions and such boringly standard calling sequences that in
practice, the issue very, very rarely comes up. (This is a more
considered viewpoint than that which I stated earlier.)
I must admit to being bemused by the great variety of places one can
interpolate `const' into a type expression, and not /actually/ being
entirely sure as to what every single one of them means. I imagine
that neat command-line tool which produces English expressions from
C type aggregates would help here.
I think that `const TYPE *' == `TYPE const *', and in fact that latter
is more consistent with the `dereference and qualify from the right'
rule, but people have tended to plump for the idiosyncratic former
option.
> void f1(char *)
> void f2(const char *)
>
> void f3(void)
> {
> char ca[32];
>
> f1(&ca[16]);
> ...
> ca[0] = '\0';
> f2(ca);
> /* Can't assume ca[0] == '\0' */
> ...
> }
My brain's asleep. Why is that? That case is surely identical to:
void f (const char *k)
{
printf("char = %d\n", *k);
}
int main ()
{
char ca[32];
*ca = 'a';
f(ca);
/* Why can't @ca@ be assumed to be 'a' here? */
}
The seeming paradox has rather puzzled me: clearly more than /just/ the
pointed-to object are, pragmatically, going to get modified: and thus
how far do the array bounds extend either way?
In the `const' case, you might say `infinitely in either direction' --
however, then you have to apply that bounding to the non-`const' case
/too/: i.e. that function that takes a non-`const' pointer is at
liberty, in the compiler's eyes, to modify /infinitely/ (well,
I think array bounds are limited to `INT_MAX' or somesuch) either side
of it: thus potentially scribbling over `const' types in memory.
It would clearly be silly if in the case of a `const char *', all ANSI
guaranteed you was that /the/ pointed-to object wasn't modified and
not anything either side: that would be a useless guarantee. Therefore,
I assume that it implies that all valid array points of that object
don't get modified. Therefore, I assume that applies to non-const,
too. /Therefore/, what about this case:
struct file {
int a;
unsigned b;
};
void b (struct file *f)
{
f->a++;
f[6]->a = 1;
}
void a ()
{
struct file f[16];
struct file *g;
g = &f[6];
g->a = 9;
b(f);
/* Compiler still thinks that @g->a == 9@ -- it doesn't know that
* it bears any relation to @f@
*/
}
Now, if ANSI has infinitely-extending array bounds as to what can be
modified based on a passed pointer, @g@ could well be trashed by b(),
/but/ then the compiler has to keep track of the fact that @g@ is a
valid array-indexed offset from @f@, and therefore flush its values
after a call to b(). Obviously you could force this with `volatile',
but that's obviously not the solution.
I ought to find my copy of the Standard, really. :-/
> I have heard that the MetaWare C compiler can perform such
> optimisation. (And, there's an ARM back end for it.) Languages
> without explicit pointers are better :-)
Where's that available from?
> Negligible space. (Most of the object file's bulk is symbol
> tables etc.)
Yup. Great.
c.
More information about the oslib-user
mailing list