From: | Andy Walker <anw@cuboid.co.uk> |
Newsgroups: | comp.compilers |
Date: | Wed, 8 May 2019 01:42:31 +0100 |
Organization: | Not very much |
References: | 19-04-021 19-04-023 19-04-037 19-04-039 19-04-042 19-04-044 19-04-047 19-05-004 19-05-006 19-05-016 19-05-020 19-05-024 19-05-025 19-05-028 19-05-029 19-05-034 19-05-045 |
Injection-Info: | gal.iecc.com; posting-host="news.iecc.com:2001:470:1f07:1126:0:676f:7373:6970"; logging-data="97477"; mail-complaints-to="abuse@iecc.com" |
Keywords: | standards, errors, optimize, comment |
Posted-Date: | 07 May 2019 22:53:09 EDT |
Content-Language: | en-GB |
On 07/05/2019 10:04, David Brown wrote:
> It will not be slower in C - because the compiler knows that "i" is
> never changed in the loop. (I'd like some way to have that enforced in
> C, but I don't know of any good method.)
There's rather little you can "enforce" in C unless the compiler
is on your side! See below.
> Just for a laugh, try this code: [largely snipped for brevity -- ANW]
> #include <stdio.h>
> int *pi = &i;
> int *pj = &j;
> printf("pi = %p, pj[-1] = %p\n", [...]
There is sanction in the Standard for adding one to a pointer to
a scalar, but not for subtracting one; so this is UB [N1570, section
6.5.6, paras 7, 8].
> [...] With no optimisation and a literal translation of
> the code, the result will be 48.
Yes, provided that the compiler doesn't enforce the Standard!
> With optimisation, the compiler knows
> that access through "pj" cannot possibly affect "i" without invoking
> undefined behaviour - so it can simplify the loop to "sum = 55;" and
> shows that result.
Quite. That's the sort of way that UB comes back to bite you.
You optimise some code, and the answer changes. There are worse
possibilities, even without going beyond reasonableness; take, for
example Bart's "struct" with four integer members that he wants to
treat as an array. Suppose further that he tries to write to the i'th
member of that array, even after checking that 0 <= i <= 3. A non-
checking compiler will allow that, even though it's UB if i > 0. An
optimising compiler may quite well, however, deduce that "therefore"
i = 0, and carry that value of "i" forward in the analysis. If the
decision whether or not to "rm -rf /" depends on the value of "i",
you can be well and truly up the creek without a paddle.
[Moderator:]
> [For the loop with the unchangable index, you can declare the index
> const and cast the places you change it, [...].
As so often, you may well get away with it, but it's UB. See
in particular footnote 132 --
" The implementation may place a const object that is not volatile
" in a read-only region of storage. "
Further, if you can change the index that way, so can a malicious or
careless writer of the loop body, which rather negates the point of
making it "const". To do it properly, it needs to be a defined and
checkable property in the language, as in, for example, Algol 68.
--
Andy Walker,
Nottingham.
[Hey, I said "but ugh". I would think that an auto const without a
constant initializer wouldn't be eligible for read-only storage since
it might have a different value each time the block is entered. -John]
Return to the
comp.compilers page.
Search the
comp.compilers archives again.