Path: csiph.com!weretis.net!feeder8.news.weretis.net!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c++
Subject: Re: C++20 concepts rocks
Date: Fri, 11 Feb 2022 05:41:28 -0800
Organization: A noiseless patient Spider
Lines: 74
Message-ID: <868ruhikqf.fsf@linuxsc.com>
References: <87k0easj5d.fsf@bsb.me.uk> <865yptlpgf.fsf@linuxsc.com> <87mtj4qd0h.fsf@bsb.me.uk> <86fsovkdjw.fsf@linuxsc.com> <877da7r7ap.fsf@bsb.me.uk> <86bkzjjs3c.fsf@linuxsc.com> <87k0e6q4j8.fsf@bsb.me.uk> <8635kukb17.fsf@linuxsc.com> <878rumptie.fsf@bsb.me.uk> <86leymiga7.fsf@linuxsc.com> <877da3n2au.fsf@bsb.me.uk> <86czjvi97y.fsf@linuxsc.com> <87czjulvm9.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: reader02.eternal-september.org; posting-host="b9455237bdb2d6ef08ab4c168ca7a31f"; logging-data="2853"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/e5kToA9YDSzIr7X/gKIxJ8wH4snMn5p8="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:OwNy3BIhw38ffR91NkLND+Z1J7E= sha1:oK/UqsAFPQwrF9aB78HMQFRIzFA=
Xref: csiph.com comp.lang.c++:82982
Ben Bacarisse writes:
> Tim Rentsch writes:
>
>> Rather than thinking about pointer values, it might help to start
>> with objects. [..illustrative examples..]
>>
>> Casting a pointer to a different type doesn't change what objects
>> it can access. At least, this rule holds in C, [...]
> Really the only issue I had is resolved by the rule that "the array" is
> always the smallest enclosing array that contains the thing pointed to
> (before any conversions of course).
Interesting. I hadn't thought of it that way before. Seems right.
I should make a clarifying statement about casting not changing
what objects can be accessed. If we have this code fragment
int foo[10][20];
extern void set_elements( int *, size_t, int )
set_elements( (int*) &foo, 10*20, -1 );
an argument could be made that set_elements() cannot use pointer
arithmetic (including that implied by use of []) on its first
argument other than to access between foo[0][0] and foo[0][19] (or
to construct a pointer to foo[0][20]). The reasoning would be that
there is no array of 200 elements, so the conditions for address
arithmetic would not be met for index values other than between 0 and
20, and so would technically be undefined behavior. It would be
surprising if that putative undefined behavior would result in the
code "doing the wrong thing", but I feel obliged to point out the
possible alternative reading nonetheless.
Even if the reading proposed above holds, set_elements() can be
written in a way that avoids the putative undefined behavior:
void
set_elements( int *v, size_t n, int value ){
while( n-- > 0 ){
*(int*)( (char*)v + n * sizeof *v ) = value;
}
}
This code has to work for the call that passes '(int*)&foo',
because all objects have an implied character array that overlays
the entire object, which is all of foo in this case.
> In the back of my mind I had thought that (at least for C) the standard
> had been written to permit huge arrays to have some or all rows in
> separate segments, while only requiring full pointer arithmetic for the
> case of a char * accessing the object's representation. But that's not
> the case, and (T *)&A can access all elements of any array A with base
> type T.
My understanding is that the underlying reasons have to do with
possible program optimization. For example, if the array foo and
the function set_elements() have been declared as shown above, and
there is a call
set_elements( foo[0], 20, 10 );
we would like a compiler to be able to assume that foo[1], foo[2],
... , foo[9], are neither changed nor referenced by this call to
set_elements().
AFAIAA all of the above statements apply to C++ as well as C
(assuming of course there is no operator overloading or anything
else along those lines). If anyone knows of any indication to the
contrary in the C++ standard I would be interested to hear about
that.