Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #126772 > unrolled thread
| Started by | lee@ansync.com |
|---|---|
| First post | 2018-02-15 17:20 -0800 |
| Last post | 2018-02-26 10:17 -0800 |
| Articles | 20 on this page of 83 — 14 participants |
Back to article view | Back to comp.lang.c
Opinion sought: Is this strictly conforming C? lee@ansync.com - 2018-02-15 17:20 -0800
Re: Opinion sought: Is this strictly conforming C? James Kuyper <jameskuyper@verizon.net> - 2018-02-15 22:15 -0500
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-16 08:44 -0800
Re: Opinion sought: Is this strictly conforming C? jameskuyper@verizon.net - 2018-02-16 11:47 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-16 13:00 -0800
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-19 12:25 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-19 13:21 -0800
Re: Opinion sought: Is this strictly conforming C? Randy Howard <rhoward.mx@EverybodyUsesIt.com> - 2018-02-19 15:26 -0600
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-19 13:59 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-19 14:38 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-19 15:21 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-19 15:59 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-19 17:11 -0800
Re: Opinion sought: Is this strictly conforming C? David Brown <david.brown@hesbynett.no> - 2018-02-20 09:17 +0100
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-20 07:58 -0800
Re: Opinion sought: Is this strictly conforming C? David Brown <david.brown@hesbynett.no> - 2018-02-20 18:21 +0100
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-20 09:25 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-20 11:52 -0800
Re: Opinion sought: Is this strictly conforming C? Richard Damon <Richard@Damon-Family.org> - 2018-02-20 22:27 -0500
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-20 23:07 -0800
Re: Opinion sought: Is this strictly conforming C? Manfred <noname@invalid.add> - 2018-02-21 14:07 +0100
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-21 09:02 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-21 09:50 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-21 12:46 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-21 13:09 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-21 15:15 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-21 15:51 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-21 17:06 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-21 17:46 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-22 00:18 -0800
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-21 22:14 -0800
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-21 11:39 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-21 14:59 -0800
Re: Opinion sought: Is this strictly conforming C? Richard Damon <Richard@Damon-Family.org> - 2018-02-21 22:14 -0500
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-22 00:50 -0800
Re: Opinion sought: Is this strictly conforming C? Richard Damon <Richard@Damon-Family.org> - 2018-02-22 07:22 -0500
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-22 12:40 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-22 13:00 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-22 13:48 -0800
Re: Opinion sought: Is this strictly conforming C? scott@slp53.sl.home (Scott Lurndal) - 2018-02-22 22:14 +0000
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-21 23:05 -0800
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-21 23:39 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-22 10:39 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-22 13:20 -0800
Re: Opinion sought: Is this strictly conforming C? asetofsymbols@gmail.com - 2018-02-23 00:30 -0800
Re: Opinion sought: Is this strictly conforming C? Manfred <noname@invalid.add> - 2018-02-16 20:05 +0100
Re: Opinion sought: Is this strictly conforming C? lee@ansync.com - 2018-02-16 11:14 -0800
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-19 11:30 -0800
Re: Opinion sought: Is this strictly conforming C? Steve Carroll <frelwizzen@gmail.com> - 2018-03-01 09:01 -0800
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-19 11:08 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-19 17:16 -0800
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-21 23:16 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-22 00:25 -0800
Re: Opinion sought: Is this strictly conforming C? Richard Damon <Richard@Damon-Family.org> - 2018-02-22 07:41 -0500
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-24 13:24 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-25 12:07 -0800
Re: Opinion sought: Is this strictly conforming C? Richard Damon <Richard@Damon-Family.org> - 2018-02-25 18:34 -0500
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-26 08:21 -0800
Re: Opinion sought: Is this strictly conforming C? Richard Damon <Richard@Damon-Family.org> - 2018-02-26 22:22 -0500
Re: Opinion sought: Is this strictly conforming C? David Brown <david.brown@hesbynett.no> - 2018-02-27 09:16 +0100
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-27 08:48 -0800
Re: Opinion sought: Is this strictly conforming C? David Brown <david.brown@hesbynett.no> - 2018-02-28 10:24 +0100
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-28 09:03 -0800
Re: Opinion sought: Is this strictly conforming C? David Brown <david.brown@hesbynett.no> - 2018-02-28 22:31 +0100
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-28 15:19 -0800
Re: Opinion sought: Is this strictly conforming C? David Brown <david.brown@hesbynett.no> - 2018-03-01 12:37 +0100
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-03-01 11:03 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-03-01 11:22 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-01 11:48 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-01 15:11 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-01 16:14 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-01 19:53 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-01 21:27 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-02 00:52 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-02 01:54 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-03 06:11 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-03-01 12:31 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-03-01 13:15 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-01 14:55 -0800
Re: Opinion sought: Is this strictly conforming C? Tim Rentsch <txr@alumni.caltech.edu> - 2018-03-03 02:19 -0800
Re: Opinion sought: Is this strictly conforming C? Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-03 03:03 -0800
Re: Opinion sought: Is this strictly conforming C? Keith Thompson <kst-u@mib.org> - 2018-02-25 15:36 -0800
Re: Opinion sought: Is this strictly conforming C? supercat@casperkitty.com - 2018-02-26 10:17 -0800
Page 2 of 5 — ← Prev page 1 [2] 3 4 5 Next page →
| From | Manfred <noname@invalid.add> |
|---|---|
| Date | 2018-02-21 14:07 +0100 |
| Message-ID | <p6jqts$1fak$1@gioia.aioe.org> |
| In reply to | #126915 |
On 2/21/2018 8:07 AM, supercat@casperkitty.com wrote:
> On Tuesday, February 20, 2018 at 9:27:55 PM UTC-6, Richard Damon wrote:
>> On 2/20/18 2:52 PM, supercat@casperkitty.com wrote:
>>> Given that K&R clearly shows that objects of arbitrary type are supposed
>>> to be fully accessible via character-type pointer, I think it would be
>>> absurd to suggest that the second shouldn't be defined. Since a pointer
>>> to an aggregate, suitably converted, is the same as a pointer to its first
>>> member or element, however, I don't see anything that would distinguish
>>> the pointer yielded by the decay of foo[0] from the pointer yielded by
>>> converting foo to a void* and then an unsigned char*.
>>
>> Yes, there is a special exemption for looking at an object of any type
>> as a character array, but that does NOT provide a general out for taking
>> a '2d array' and addressing it as a 1d array.
>>
>> Take your example above and change unsigned char to unsigned int, and
>> you have lost that specific exemption, and ran into the domain of
>> undefined behavior. Yes, unless the implementation has taken specific
>> steps to keep if from working, if is very likely to work, but that can
>> be the sort of thing that undefined behavior does.
>
> Looking through C89 draft, I see nothing to suggest that the pointer
> arithmetic rules for character types are in any way special compared
> with those for other types. The rationale notes that code expects to
> be able to treat objects as though they are arrays of character types,
> but I see nothing within the text of the Standard that would justify
> that unless it were implied by other aspects of how pointer arithmetic
> works.
In my understanding, this would be implied by the definition of
representation of types: 6.2.6.1 p2 ("... objects are composed of
contiguous sequences of one or more bytes ...") together with p4 ("Two
values ... with the same object representation compare equal ...", which
is a definition of object identity)
In cases involving pointers which do not identify recognizable
> objects of static or automatic duration, the rules about pointers to
> structures and unions would suffice to describe how things must behave.
>
> Given, for example:
>
> int test1(struct s45 *p, int i)
> {
> int *ip = p->arr[0];
> ip = ((struct s20*)ip)->arr;
> return ip[i];
> }
>
> int testIt(int x)
> {
> union { struct s45 v45; struct s20 v20; }
> u = {0};
> return test1(&u.v45, x);
> }
>
> The behavior of test3 would be described by the Standard for values of x
> up to 20, since it specifies that the address of u.v45.arr[0] is the same
> as the address of u.v45, which is in turn the same as the address of
> u.v20. A compiler processing test1 may have no way of knowing that
> testIt declares a union type, but that shouldn't matter. A compiler could
> generate the same code for test1 without having to know or care about whether
> it's receiving a pointer to a stand-alone structure object, a structure that
> is within a union, or a region of allocated storage, and I've seen no
> indication that the authors of C89 expected or intended to encourage
> compilers to do otherwise.
>
> If the behavior of testIt would be defined under C89 for values of x up to
> 20, and I see no reason the equivalence of pointers to aggregates and
> their members wouldn't suffice to define it, is there any reason it would
> not be defined if the assignment to ip were omitted (leaving it with the
> directly-assigned address of p->arr[0])? What if the variable ip were
> omitted and the lvalue expression were p->arr[0][i]? Is there anything in
> C89 that would suggest that pointers carry with them information about
> their provenance?
>
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-21 09:02 -0800 |
| Message-ID | <9d99d555-a3c0-4662-92a0-968f60426206@googlegroups.com> |
| In reply to | #126925 |
On Wednesday, February 21, 2018 at 7:07:27 AM UTC-6, Manfred wrote:
> On 2/21/2018 8:07 AM, supercat@casperkitty.com wrote:
> > Looking through C89 draft, I see nothing to suggest that the pointer
> > arithmetic rules for character types are in any way special compared
> > with those for other types. The rationale notes that code expects to
> > be able to treat objects as though they are arrays of character types,
> > but I see nothing within the text of the Standard that would justify
> > that unless it were implied by other aspects of how pointer arithmetic
> > works.
>
> In my understanding, this would be implied by the definition of
> representation of types: 6.2.6.1 p2 ("... objects are composed of
> contiguous sequences of one or more bytes ...") together with p4 ("Two
> values ... with the same object representation compare equal ...", which
> is a definition of object identity)
Is there any reason that the implications of that would only be applicable
when using character-pointer arithmetic, and not when using pointers to
objects of other type whose layout is known?
I have no problem with the idea that the Standard should allow compilers
to assume that the [] operator will only be used on an lvalue of array type
to yield an lvalue within the array. Doing so, however, would require
making a distinction between array[index] and ((elementType*)array)[index],
and the Standard does not yet make one even though making such a distinction
would allow optimizations which are not otherwise possible.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-02-21 09:50 -0800 |
| Message-ID | <lnzi42kz9r.fsf@kst-u.example.com> |
| In reply to | #126925 |
Manfred <noname@invalid.add> writes:
> On 2/21/2018 8:07 AM, supercat@casperkitty.com wrote:
[...]
>> Looking through C89 draft, I see nothing to suggest that the pointer
>> arithmetic rules for character types are in any way special compared
>> with those for other types. The rationale notes that code expects to
>> be able to treat objects as though they are arrays of character types,
>> but I see nothing within the text of the Standard that would justify
>> that unless it were implied by other aspects of how pointer arithmetic
>> works.
>
> In my understanding, this would be implied by the definition of
> representation of types: 6.2.6.1 p2 ("... objects are composed of
> contiguous sequences of one or more bytes ...") together with p4 ("Two
> values ... with the same object representation compare equal ...", which
> is a definition of object identity)
It is today, but in C89 the wording about sequences of bytes
appears in the definition of "object":
* Object --- a region of data storage in the execution environment,
the contents of which can represent values. Except for
bit-fields, objects are composed of contiguous sequences of
one or more bytes, the number, order, and encoding of which are
either explicitly specified or implementation-defined.
and the phrase "object representation" doesn't appear at all.
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-21 12:46 -0800 |
| Message-ID | <95ef2dbd-24aa-415b-ada7-6e933b27cf2b@googlegroups.com> |
| In reply to | #126939 |
On Wednesday, February 21, 2018 at 11:50:51 AM UTC-6, Keith Thompson wrote:
> Manfred <noname@invalid.add> writes:
> > On 2/21/2018 8:07 AM, supercat@casperkitty.com wrote:
> [...]
> >> Looking through C89 draft, I see nothing to suggest that the pointer
> >> arithmetic rules for character types are in any way special compared
> >> with those for other types. The rationale notes that code expects to
> >> be able to treat objects as though they are arrays of character types,
> >> but I see nothing within the text of the Standard that would justify
> >> that unless it were implied by other aspects of how pointer arithmetic
> >> works.
> >
> > In my understanding, this would be implied by the definition of
> > representation of types: 6.2.6.1 p2 ("... objects are composed of
> > contiguous sequences of one or more bytes ...") together with p4 ("Two
> > values ... with the same object representation compare equal ...", which
> > is a definition of object identity)
>
> It is today, but in C89 the wording about sequences of bytes
> appears in the definition of "object":
>
> * Object --- a region of data storage in the execution environment,
> the contents of which can represent values. Except for
> bit-fields, objects are composed of contiguous sequences of
> one or more bytes, the number, order, and encoding of which are
> either explicitly specified or implementation-defined.
>
> and the phrase "object representation" doesn't appear at all.
Is there anything in C89 that would suggest that character pointers are
exempt from any addressing or other restrictions that would apply to other
pointer types beyond the facts that data of other types may be accessed
using character-type lvalues, other pointer types may have alignment
restrictions which character pointers cannot, and non-character types may
have padding bits and/or trap representations while character types
cannot? In particular, is there anything that would suggest that a
character pointer to an element of an array within a larger array would
have a unique ability access the entire outer array (compared with a non-
character pointer)?
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-02-21 13:09 -0800 |
| Message-ID | <lnr2pekq2p.fsf@kst-u.example.com> |
| In reply to | #126953 |
supercat@casperkitty.com writes:
> On Wednesday, February 21, 2018 at 11:50:51 AM UTC-6, Keith Thompson wrote:
>> Manfred <noname@invalid.add> writes:
>> > On 2/21/2018 8:07 AM, supercat@casperkitty.com wrote:
>> [...]
>> >> Looking through C89 draft, I see nothing to suggest that the pointer
>> >> arithmetic rules for character types are in any way special compared
>> >> with those for other types. The rationale notes that code expects to
>> >> be able to treat objects as though they are arrays of character types,
>> >> but I see nothing within the text of the Standard that would justify
>> >> that unless it were implied by other aspects of how pointer arithmetic
>> >> works.
>> >
>> > In my understanding, this would be implied by the definition of
>> > representation of types: 6.2.6.1 p2 ("... objects are composed of
>> > contiguous sequences of one or more bytes ...") together with p4 ("Two
>> > values ... with the same object representation compare equal ...", which
>> > is a definition of object identity)
>>
>> It is today, but in C89 the wording about sequences of bytes
>> appears in the definition of "object":
>>
>> * Object --- a region of data storage in the execution environment,
>> the contents of which can represent values. Except for
>> bit-fields, objects are composed of contiguous sequences of
>> one or more bytes, the number, order, and encoding of which are
>> either explicitly specified or implementation-defined.
>>
>> and the phrase "object representation" doesn't appear at all.
>
> Is there anything in C89 that would suggest that character pointers are
> exempt from any addressing or other restrictions that would apply to other
> pointer types beyond the facts that data of other types may be accessed
> using character-type lvalues, other pointer types may have alignment
> restrictions which character pointers cannot, and non-character types may
> have padding bits and/or trap representations while character types
> cannot? In particular, is there anything that would suggest that a
> character pointer to an element of an array within a larger array would
> have a unique ability access the entire outer array (compared with a non-
> character pointer)?
The specialness of character types with respect to accessing objects was
not quite as explicit in C90 as in later editions, but it's there.
Section 6.3 says:
An object shall have its stored value accessed only by an lvalue
that has one of the following types:
* the declared type of the object,
* a qualified version of the declared type of the object,
* a type that is the signed or unsigned type corresponding to the
declared type of the object,
* a type that is the signed or unsigned type corresponding to a
qualified version of the declared type of the object,
* an aggregate or union type that includes one of the aforementioned
types among its members (including, recursively, a member of a
subaggregate or contained union), or
* a character type.
with a footnote:
The intent of this list is to specify those circumstances in which
an object may or may not be aliased.
Given a declaration
int a[5][5];
wouldn't evaluating
a[1][7]
require aliasing an array object as a different array type?
If a C90 implementation forced a run-time trap on an attempt to evaluate
a[1][7], what (normative) clause of C90 would it violate?
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-21 15:15 -0800 |
| Message-ID | <5b4dbe5b-b7b0-48f4-8511-d443695f0e5b@googlegroups.com> |
| In reply to | #126957 |
On Wednesday, February 21, 2018 at 3:09:31 PM UTC-6, Keith Thompson wrote: > supercat@casperkitty.com writes: > > Is there anything in C89 that would suggest that character pointers are > > exempt from any addressing or other restrictions that would apply to other > > pointer types beyond the facts that data of other types may be accessed > > using character-type lvalues, other pointer types may have alignment > > restrictions which character pointers cannot, and non-character types may > > have padding bits and/or trap representations while character types > > cannot? In particular, is there anything that would suggest that a > > character pointer to an element of an array within a larger array would > > have a unique ability access the entire outer array (compared with a non- > > character pointer)? > > The specialness of character types with respect to accessing objects was > not quite as explicit in C90 as in later editions, but it's there. > Section 6.3 says: > > An object shall have its stored value accessed only by an lvalue > that has one of the following types: > * a character type. > > with a footnote: > > The intent of this list is to specify those circumstances in which > an object may or may not be aliased. I identified all of the special rules and guarantees I am aware of with regard to character pointers, including the one you list. Are there any that I missed? > Given a declaration > int a[5][5]; > wouldn't evaluating > a[1][7] > require aliasing an array object as a different array type? > > If a C90 implementation forced a run-time trap on an attempt to evaluate > a[1][7], what (normative) clause of C90 would it violate? The code above would create an array object sized to hold a total of 25 values of type "int". Assume "int" is 4 bytes; the size of the object would be 100 bytes. According to C89 3.3.6, the subexpression a[1] would multiply the value in the brackets (i.e. 1) by the size of *a [i.e. 20], and add that result to the address of the aforementioned array object. Then applying [7] to that would multiply the value 7 by the size of **a [i.e. 4] and that to the just-computed address, yielding an address 48 bytes past the start of the 100-byte array object. I would expect that quality compilers will typically have a variety of conforming and non-conforming modes, some of which will reject some programs that are unambiguously Strictly Conforming. The usefulness of having a compiler accept or squawk at or trap certain constructs is largely orthogonal to the question of whether those constructs are defined or forbidden by the Standard.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-02-21 15:51 -0800 |
| Message-ID | <lnmv01lx50.fsf@kst-u.example.com> |
| In reply to | #126961 |
supercat@casperkitty.com writes:
> On Wednesday, February 21, 2018 at 3:09:31 PM UTC-6, Keith Thompson wrote:
[...]
>> Given a declaration
>> int a[5][5];
>> wouldn't evaluating
>> a[1][7]
>> require aliasing an array object as a different array type?
>>
>> If a C90 implementation forced a run-time trap on an attempt to evaluate
>> a[1][7], what (normative) clause of C90 would it violate?
>
> The code above would create an array object sized to hold a total of 25
> values of type "int". Assume "int" is 4 bytes; the size of the object
> would be 100 bytes.
Yes, it would create an array object that contains 25 int objects, but
not an array object of type int[25]. Each of the 5 elements of a is of
type int[5].
> According to C89 3.3.6, the subexpression a[1] would multiply the value in
> the brackets (i.e. 1) by the size of *a [i.e. 20], and add that result to
> the address of the aforementioned array object. Then applying [7] to that
> would multiply the value 7 by the size of **a [i.e. 4] and that to the
> just-computed address, yielding an address 48 bytes past the start of the
> 100-byte array object.
Yes, the C89 definition of pointer arithmetic refers to multiplication.
(In my opinion the current definition, which does not, is better.)
C89 3.3.6:
When an expression that has integral type is added to
or subtracted from a pointer, the integral value is first
multiplied by the size of the object pointed to. The result
has the type of the pointer operand. If the pointer operand
points to a member of an array object, and the array object is
large enough, the result points to a member of the same array
object, appropriately offset from the original member.
For a[1][7] to work the way you want it to, there would have be an array
object of type int[N], with N > 7. (The most straightforward way to
have this would be to treat all of a as an array object of type
int[25].) The elements of a are not int objects; they're array objects
of type int[5].
C89 3.3 ("An object shall have its stored value accessed only by an
lvalue that has one of the following types:") does not permit accessing
a, or part of a, with an lvalue of type int[N] with N > 7?
What object of type int[N] do you believe exists?
> I would expect that quality compilers will typically have a variety of
> conforming and non-conforming modes, some of which will reject some
> programs that are unambiguously Strictly Conforming. The usefulness of
> having a compiler accept or squawk at or trap certain constructs is largely
> orthogonal to the question of whether those constructs are defined or
> forbidden by the Standard.
I didn't ask whether a such an implementation would be useful. I asked
what (normative) clause of C90 it would violate.
I suppose I should clarify that I'm not commenting on whether the
behavior of a[1][7] *should* be defined. I'm discussing whether the C89
standard actually does define its behavior.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-21 17:06 -0800 |
| Message-ID | <2ea2a3c6-3578-4d3c-b366-f19d4741245e@googlegroups.com> |
| In reply to | #126963 |
On Wednesday, February 21, 2018 at 5:51:37 PM UTC-6, Keith Thompson wrote:
> supercat@casperkitty.com writes:
> > The code above would create an array object sized to hold a total of 25
> > values of type "int". Assume "int" is 4 bytes; the size of the object
> > would be 100 bytes.
>
> Yes, it would create an array object that contains 25 int objects, but
> not an array object of type int[25]. Each of the 5 elements of a is of
> type int[5].
There would be a 100-byte array object.
> > According to C89 3.3.6, the subexpression a[1] would multiply the value in
> > the brackets (i.e. 1) by the size of *a [i.e. 20], and add that result to
> > the address of the aforementioned array object. Then applying [7] to that
> > would multiply the value 7 by the size of **a [i.e. 4] and that to the
> > just-computed address, yielding an address 48 bytes past the start of the
> > 100-byte array object.
>
> Yes, the C89 definition of pointer arithmetic refers to multiplication.
> (In my opinion the current definition, which does not, is better.)
So you acknowledge that there was a change.
> C89 3.3.6:
> When an expression that has integral type is added to
> or subtracted from a pointer, the integral value is first
> multiplied by the size of the object pointed to. The result
> has the type of the pointer operand. If the pointer operand
> points to a member of an array object, and the array object is
> large enough, the result points to a member of the same array
> object, appropriately offset from the original member.
>
> For a[1][7] to work the way you want it to, there would have be an array
> object of type int[N], with N > 7. (The most straightforward way to
> have this would be to treat all of a as an array object of type
> int[25].) The elements of a are not int objects; they're array objects
> of type int[5].
The Standard could have been clearer if it didn't overload the term
"object" so much. The Standard clearly intends that the code:
int arr[5], p=a+5, q=p-1;
should have defined behavior even though "p" doesn't point to any object;
thus "the size of the object pointed to" presumably means "the size of
the lvalue yielded by dereferencing a pointer of that type".
I would suggest that the Standard also clearly intends that the code:
int *p = malloc(3 * sizeof (int));
if (p) p[2] = 5;
should have defined behavior even though there is no int[]. The malloc()
function would be pretty well useless if its return pointer couldn't be
treated, for purposes of pointer arithmetic, as though it pointed to an
array object.
> I didn't ask whether a such an implementation would be useful. I asked
> what (normative) clause of C90 it would violate.
The one which describes how pointer arithmetic works. There exists an
array object. The lvalue a[1] points to four bytes within it. Adding
28 to the address of a[1] would yield the address of different four
bytes within that same array object.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-02-21 17:46 -0800 |
| Message-ID | <lninaplrtd.fsf@kst-u.example.com> |
| In reply to | #126970 |
supercat@casperkitty.com writes:
> On Wednesday, February 21, 2018 at 5:51:37 PM UTC-6, Keith Thompson wrote:
>> supercat@casperkitty.com writes:
>> > The code above would create an array object sized to hold a total of 25
>> > values of type "int". Assume "int" is 4 bytes; the size of the object
>> > would be 100 bytes.
>>
>> Yes, it would create an array object that contains 25 int objects, but
>> not an array object of type int[25]. Each of the 5 elements of a is of
>> type int[5].
>
> There would be a 100-byte array object.
Yes, you already said that, and I already agreed.
>> > According to C89 3.3.6, the subexpression a[1] would multiply the value in
>> > the brackets (i.e. 1) by the size of *a [i.e. 20], and add that result to
>> > the address of the aforementioned array object. Then applying [7] to that
>> > would multiply the value 7 by the size of **a [i.e. 4] and that to the
>> > just-computed address, yielding an address 48 bytes past the start of the
>> > 100-byte array object.
>>
>> Yes, the C89 definition of pointer arithmetic refers to multiplication.
>> (In my opinion the current definition, which does not, is better.)
>
> So you acknowledge that there was a change.
Of course, the wording was changed. (In my opinion it was an
improvement; C89's reference to multiplication was imprecise.)
I'm not aware that the changed wording changed the semantics, but I
haven't studied it closely enough to be sure. Do you think the
semantics changed?
>> C89 3.3.6:
>> When an expression that has integral type is added to
>> or subtracted from a pointer, the integral value is first
>> multiplied by the size of the object pointed to. The result
>> has the type of the pointer operand. If the pointer operand
>> points to a member of an array object, and the array object is
>> large enough, the result points to a member of the same array
>> object, appropriately offset from the original member.
>>
>> For a[1][7] to work the way you want it to, there would have be an array
>> object of type int[N], with N > 7. (The most straightforward way to
>> have this would be to treat all of a as an array object of type
>> int[25].) The elements of a are not int objects; they're array objects
>> of type int[5].
>
> The Standard could have been clearer if it didn't overload the term
> "object" so much. The Standard clearly intends that the code:
>
> int arr[5], p=a+5, q=p-1;
>
> should have defined behavior even though "p" doesn't point to any object;
> thus "the size of the object pointed to" presumably means "the size of
> the lvalue yielded by dereferencing a pointer of that type".
C11 (N1570 6.5.6) is clearer on this point, though the wording IMHO
could still be fixed up a bit. It discusses pointer arithmetic where
the pointer operand points just past the end of an array.
> I would suggest that the Standard also clearly intends that the code:
>
> int *p = malloc(3 * sizeof (int));
> if (p) p[2] = 5;
>
> should have defined behavior even though there is no int[]. The malloc()
> function would be pretty well useless if its return pointer couldn't be
> treated, for purposes of pointer arithmetic, as though it pointed to an
> array object.
I think the effective type rules cover this. (C89/C90 didn't discuss
effective types.)
>> I didn't ask whether a such an implementation would be useful. I asked
>> what (normative) clause of C90 it would violate.
>
> The one which describes how pointer arithmetic works. There exists an
> array object. The lvalue a[1] points to four bytes within it.
lvalues don't point. The lvalue a[1] is an expression that designates
an object of type int[5]. Since it's an array expression, it's
converted to a pointer expression which is no longer an lvalue. The
value of that pointer expression is the address of an int object.
> Adding
> 28 to the address of a[1] would yield the address of different four
> bytes within that same array object.
What array object are referring to? You seem to be assuming the
existence of an object of type int[25], but you haven't demonstrated
where the C89 standard says that such an object exists, or that a can be
accessed as if it were such an object.
"If the pointer operand points to a member of an array object"
The array object in question is a[1]. The member in question is
a[1][0].
"and the array object is large enough,"
The array object a[1] has only 5 members, so it isn't large enough.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-22 00:18 -0800 |
| Message-ID | <eadff3ea-f968-4306-a1f7-83c42d1e5e11@googlegroups.com> |
| In reply to | #126971 |
On Wednesday, February 21, 2018 at 7:46:34 PM UTC-6, Keith Thompson wrote: > supercat@casperkitty.com writes: > > So you acknowledge that there was a change. > > Of course, the wording was changed. (In my opinion it was an > improvement; C89's reference to multiplication was imprecise.) > > I'm not aware that the changed wording changed the semantics, but I > haven't studied it closely enough to be sure. Do you think the > semantics changed? The old wording could be interpreted as supporting some corner-case behaviors which were processed consistently and usefully by existing implementations. There was no perceived need to worry about whether a compiler could do something else while still being conforming because it was recognized (by the authors of the Standard, no less) that the Standard does not seek to mandate everything needed to make an implementation useful for any particular purpose. > >> C89 3.3.6: > >> When an expression that has integral type is added to > >> or subtracted from a pointer, the integral value is first > >> multiplied by the size of the object pointed to. The result > >> has the type of the pointer operand. If the pointer operand > >> points to a member of an array object, and the array object is > >> large enough, the result points to a member of the same array > >> object, appropriately offset from the original member. > >> > >> For a[1][7] to work the way you want it to, there would have be an array > >> object of type int[N], with N > 7. (The most straightforward way to > >> have this would be to treat all of a as an array object of type > >> int[25].) The elements of a are not int objects; they're array objects > >> of type int[5]. > > > > The Standard could have been clearer if it didn't overload the term > > "object" so much. The Standard clearly intends that the code: > > > > int arr[5], p=a+5, q=p-1; > > > > should have defined behavior even though "p" doesn't point to any object; > > thus "the size of the object pointed to" presumably means "the size of > > the lvalue yielded by dereferencing a pointer of that type". > > C11 (N1570 6.5.6) is clearer on this point, though the wording IMHO > could still be fixed up a bit. It discusses pointer arithmetic where > the pointer operand points just past the end of an array. I don't think C89 is unclear here. It's imprecise, but I think it's obvious what it meant. If there were a defined term for a pointer's target type, [e.g. the target type of "int volatile*" is "int volatile"] then referring the size of the pointer's target type would be clear and precise, but I see no basis for confusion there. > > I would suggest that the Standard also clearly intends that the code: > > > > int *p = malloc(3 * sizeof (int)); > > if (p) p[2] = 5; > > > > should have defined behavior even though there is no int[]. The malloc() > > function would be pretty well useless if its return pointer couldn't be > > treated, for purposes of pointer arithmetic, as though it pointed to an > > array object. > > I think the effective type rules cover this. (C89/C90 didn't discuss > effective types.) The Effective Type rules only determine whether an lvalue of a given type can be used to access a region of storage. Pointer arithmetic is not considered "access", and thus the Effective Type rules have nothing to do with it. > > The one which describes how pointer arithmetic works. There exists an > > array object. The lvalue a[1] points to four bytes within it. > > lvalues don't point. The lvalue a[1] is an expression that designates > an object of type int[5]. Since it's an array expression, it's > converted to a pointer expression which is no longer an lvalue. The > value of that pointer expression is the address of an int object. Fair enough. It's the value produced by pointer decomposition which points. > > Adding > > 28 to the address of a[1] would yield the address of different four > > bytes within that same array object. > > What array object are referring to? You seem to be assuming the > existence of an object of type int[25], but you haven't demonstrated > where the C89 standard says that such an object exists, or that a can be > accessed as if it were such an object. Is there anything in C89 which specifies that pointer arithmetic for char* is allowed to access through enclosing arrays, but pointer arithmetic on other types isn't? Or is the language defined by C89 a broken offshoot of the language which became popular in the 1980s and 1990s?
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2018-02-21 22:14 -0800 |
| Message-ID | <kfnh8q9v9d3.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #126957 |
Keith Thompson <kst-u@mib.org> writes: > The specialness of character types with respect to accessing objects was > not quite as explicit in C90 as in later editions, but it's there. > Section 6.3 says: > > An object shall have its stored value accessed only by an lvalue > that has one of the following types: > > * the declared type of the object, > > * a qualified version of the declared type of the object, > > * a type that is the signed or unsigned type corresponding to the > declared type of the object, > > * a type that is the signed or unsigned type corresponding to a > qualified version of the declared type of the object, > > * an aggregate or union type that includes one of the aforementioned > types among its members (including, recursively, a member of a > subaggregate or contained union), or > > * a character type. > > with a footnote: > > The intent of this list is to specify those circumstances in which > an object may or may not be aliased. > > Given a declaration > int a[5][5]; > wouldn't evaluating > a[1][7] > require aliasing an array object as a different array type? Not as far as the Standard is concerned, no. The rules in this section are only about accessing. The expression a[1][7] will, if evaluated, result in access (or possibly accesses) only of type int. (I'm ignoring the out-of-range index value, which doesn't change what type would be accessed.)
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2018-02-21 11:39 -0800 |
| Message-ID | <kfny3jmuo7w.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #126913 |
Richard Damon <Richard@Damon-Family.org> writes:
> On 2/20/18 2:52 PM, supercat@casperkitty.com wrote:
>
>> On Tuesday, February 20, 2018 at 11:26:04 AM UTC-6, Keith Thompson wrote:
>>
>>> Since the behavior of out-of-bounds array indexing is undefined,
>>> implementations are permitted to perform bounds checking.
>>> For example, an implementation might generate code that traps on
>>> something like:
>>>
>>> int arr[10];
>>> arr[20] = 42;
>>>
>>> I see nothing in C89/C90, in C99, or in C11 that would prevent an
>>> implementation from trapping on:
>>>
>>> int arr2[5][5];
>>> arr2[1][7] = 42;
>>
>> Is there anything in the Standard that would distinguish:
>>
>> unsigned char foo[5][7];
>>
>> void test(void)
>> {
>> int i;
>> for (i=0; i<35; i++)
>> printf("%02X", foo[0][i]);
>> }
>>
>> from
>>
>> void hexdump(void *dat, int n)
>> {
>> int i;
>> unsigned char *p = dat;
>> for (i=0; i<35; i++)
>> printf("%02X", p[i]);
>> }
>>
>> unsigned char foo[5][7];
>>
>> void test(void)
>> {
>> hexdump(foo,35);
>> }
>>
>> Given that K&R clearly shows that objects of arbitrary type are supposed
>> to be fully accessible via character-type pointer, I think it would be
>> absurd to suggest that the second shouldn't be defined. Since a pointer
>> to an aggregate, suitably converted, is the same as a pointer to its first
>> member or element, however, I don't see anything that would distinguish
>> the pointer yielded by the decay of foo[0] from the pointer yielded by
>> converting foo to a void* and then an unsigned char*.
>
> Yes, there is a special exemption for looking at an object of any type
> as a character array, but that does NOT provide a general out for
> taking a '2d array' and addressing it as a 1d array.
>
> Take your example above and change unsigned char to unsigned int, and
> you have lost that specific exemption, and ran into the domain of
> undefined behavior. [...]
I think your perspective here is a little bit off. I grant you
the Standard is unclear about what it means to say the rules are
in such cases. I believe though that the principle intended is
the outcome depends on the extent of what is addressed, not on
its shape. Consider an example like the following (disclaimer:
just typed in, not compiled) -
int p[10000];
int (*q)[100] = (int (*)[100]) &p;
// inthexdump() is like hexdump() but uses int * to access
// elements. (also inthexdump() uses the parameter passed
// in rather than a constant '35' as the loop limit.)
inthexdump( q, 10000 );
inthexdump( q[0], 10000 );
The first call to inthexdump() is meant to be defined behavior,
because q can refer to all of p.
The second call to inthexdump() is meant to be undefined behavior,
because q[0] refers only to the first 100 elements of p. It
doesn't matter how p was declared. What matters is the extent
of the memory available based on how the address to it was
created. Using q rather than q[0] makes a difference because
q allows access to all of q[i][j], 0 <= i, j < 100, whereas
q[0] allows access only to q[0][j]. That the declared object
underneath is a 10,000 element one-dimensional array makes
no difference.
Let me emphasize here that the above is my reading of what was
intended. I think it's a good interpretation based on everything
I've read, but I don't remember any specific text that says so.
(Also I am ignoring any question about alignment of the two array
types, assuming temporarily for the sake of discussion that it
isn't an issue.)
Do you see what I'm trying to get at here? If you do, does this
sound right to you, or do you have a different take on things?
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-21 14:59 -0800 |
| Message-ID | <8bc7563c-4150-42d5-adee-9ead8d99bb83@googlegroups.com> |
| In reply to | #126949 |
On Wednesday, February 21, 2018 at 1:39:27 PM UTC-6, Tim Rentsch wrote: > its shape. Consider an example like the following (disclaimer: > just typed in, not compiled) - > > int p[10000]; > int (*q)[100] = (int (*)[100]) &p; > // inthexdump() is like hexdump() but uses int * to access > // elements. (also inthexdump() uses the parameter passed > // in rather than a constant '35' as the loop limit.) > inthexdump( q, 10000 ); > inthexdump( q[0], 10000 ); > > The first call to inthexdump() is meant to be defined behavior, > because q can refer to all of p. > > The second call to inthexdump() is meant to be undefined behavior, > because q[0] refers only to the first 100 elements of p. It > doesn't matter how p was declared. It would certainly be useful to have a way of distinguishing a pointer which might be used to access an entire array from one which will only be used to access a small part of it, but for compilers to blithely assume that the address of an inner object will never be used to derive pointers to the outer object would be dangerous, and would irredeemably break a lot of code. Simply inviting compilers to assume that a function that receives a pointer to an inner object will never use it to access anything beyond that object's boundaries, however, is crazy and dangerous. If the hexdump function accepted an "int*" rather than a "void*", and did not cast or convert the pointer before use, then it might be reasonable for a compiler that can see the inner code to assume that the function would not use the pointer to access outside the inner array. Code which needed to pass the whole array would then have to cast the array's type to "int*" before doing so, and such a cast should be a great big neon sign to the compiler that it needs to watch out for aliasing. Unfortunately, the proposal I've read regarding pointer provenance [see http://www.open-std.org/JTC1/SC22/WG14/www/docs/n2012.htm ] seems to want to track pointer provenance to the ends of the earth and back without any clean way for a programmer to tell the compiler "This pointer is going to be used in weird ways you aren't likely to understand, so don't try to optimize operations on other objects across operations which visibly involve this pointer". If there were recognized practical means of telling the compiler that something weird was going on, it would make sense to deprecate code that does weird things without telling the compiler. As yet, however, no such means exist.
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2018-02-21 22:14 -0500 |
| Message-ID | <9AqjC.43342$Mx3.33982@fx18.iad> |
| In reply to | #126960 |
On 2/21/18 5:59 PM, supercat@casperkitty.com wrote: > On Wednesday, February 21, 2018 at 1:39:27 PM UTC-6, Tim Rentsch wrote: >> its shape. Consider an example like the following (disclaimer: >> just typed in, not compiled) - >> >> int p[10000]; >> int (*q)[100] = (int (*)[100]) &p; >> // inthexdump() is like hexdump() but uses int * to access >> // elements. (also inthexdump() uses the parameter passed >> // in rather than a constant '35' as the loop limit.) >> inthexdump( q, 10000 ); >> inthexdump( q[0], 10000 ); >> >> The first call to inthexdump() is meant to be defined behavior, >> because q can refer to all of p. >> >> The second call to inthexdump() is meant to be undefined behavior, >> because q[0] refers only to the first 100 elements of p. It >> doesn't matter how p was declared. > > It would certainly be useful to have a way of distinguishing a pointer > which might be used to access an entire array from one which will only be > used to access a small part of it, but for compilers to blithely assume > that the address of an inner object will never be used to derive pointers > to the outer object would be dangerous, and would irredeemably break a lot > of code. Simply inviting compilers to assume that a function that receives > a pointer to an inner object will never use it to access anything beyond > that object's boundaries, however, is crazy and dangerous. > > If the hexdump function accepted an "int*" rather than a "void*", and did > not cast or convert the pointer before use, then it might be reasonable for > a compiler that can see the inner code to assume that the function would > not use the pointer to access outside the inner array. Code which needed > to pass the whole array would then have to cast the array's type to "int*" > before doing so, and such a cast should be a great big neon sign to the > compiler that it needs to watch out for aliasing. > > Unfortunately, the proposal I've read regarding pointer provenance [see > > http://www.open-std.org/JTC1/SC22/WG14/www/docs/n2012.htm > > ] seems to want to track pointer provenance to the ends of the earth and > back without any clean way for a programmer to tell the compiler "This > pointer is going to be used in weird ways you aren't likely to understand, > so don't try to optimize operations on other objects across operations > which visibly involve this pointer". > > If there were recognized practical means of telling the compiler that > something weird was going on, it would make sense to deprecate code that > does weird things without telling the compiler. As yet, however, no such > means exist. > 'Something weird' in other words, I am going to break the rules and create undefined behavior, but I want you to do what I mean, not what the rules say you can.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-22 00:50 -0800 |
| Message-ID | <d635f6b3-b0b4-4f66-b3a3-e938e4397c7b@googlegroups.com> |
| In reply to | #126972 |
On Wednesday, February 21, 2018 at 9:14:41 PM UTC-6, Richard Damon wrote:
> On 2/21/18 5:59 PM, supercat@casperkitty.com wrote:
> > If there were recognized practical means of telling the compiler that
> > something weird was going on, it would make sense to deprecate code that
> > does weird things without telling the compiler. As yet, however, no such
> > means exist.
> >
>
> 'Something weird' in other words, I am going to break the rules and
> create undefined behavior, but I want you to do what I mean, not what
> the rules say you can.
More like "I want the code compiled according to the semantics that
Dennis Ritchie invented in the 1970s, and which most compilers process
with optimizations disabled, but a compiler may make certain simplifying
assumptions when there's no particular evidence to suggest that they
won't hold.
Consider the three functions:
void weird1(float *p1, char *p2)
{
if (*p1) *p2|=1;
return *p1;
}
void weird2(float *p1, float *p2)
{
if (*p1) *(char*) p2|=1;
return *p1;
}
void weird3(float *p1, float *p2)
{
if (*p1) *(uint32_t*) p2|=1;
return *p1;
}
A compiler could generate smaller code if it could assume that *p1 will
not be accessed by anything between the "if" and the "return". In the
absence of aliasing rules, would there be anything in any of those
functions that might suggest whether such an assumption would be likely
to cause trouble?
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2018-02-22 07:22 -0500 |
| Message-ID | <wCyjC.96309$UK7.10543@fx06.iad> |
| In reply to | #126983 |
On 2/22/18 3:50 AM, supercat@casperkitty.com wrote:
> On Wednesday, February 21, 2018 at 9:14:41 PM UTC-6, Richard Damon wrote:
>> On 2/21/18 5:59 PM, supercat@casperkitty.com wrote:
>>> If there were recognized practical means of telling the compiler that
>>> something weird was going on, it would make sense to deprecate code that
>>> does weird things without telling the compiler. As yet, however, no such
>>> means exist.
>>>
>>
>> 'Something weird' in other words, I am going to break the rules and
>> create undefined behavior, but I want you to do what I mean, not what
>> the rules say you can.
>
> More like "I want the code compiled according to the semantics that
> Dennis Ritchie invented in the 1970s, and which most compilers process
> with optimizations disabled, but a compiler may make certain simplifying
> assumptions when there's no particular evidence to suggest that they
> won't hold.
>
> Consider the three functions:
>
> void weird1(float *p1, char *p2)
> {
> if (*p1) *p2|=1;
> return *p1;
> }
> void weird2(float *p1, float *p2)
> {
> if (*p1) *(char*) p2|=1;
> return *p1;
> }
> void weird3(float *p1, float *p2)
> {
> if (*p1) *(uint32_t*) p2|=1;
> return *p1;
> }
>
> A compiler could generate smaller code if it could assume that *p1 will
> not be accessed by anything between the "if" and the "return". In the
> absence of aliasing rules, would there be anything in any of those
> functions that might suggest whether such an assumption would be likely
> to cause trouble?
>
No, you mean I want it to work as I want to interpret the language that
Dennis Ritchie invented in the 1970s, as maybe it happened to work on
the particular implementation that I used, even if not define or
required by that work.
Give me a statement in K&R that says that the above code is 'valid',
that accessing an object via a pointer to the wrong type (that isn't a
char type) MUST do what you want.
Note also, I believe that every (and certainly most)) implementation has
a way to tell it to work the way you want, it just might not be the
default way to execute it.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-22 12:40 -0800 |
| Message-ID | <441d0e76-1811-427b-af27-bc07a9070888@googlegroups.com> |
| In reply to | #126984 |
On Thursday, February 22, 2018 at 6:23:04 AM UTC-6, Richard Damon wrote:
> On 2/22/18 3:50 AM, supercat@casperkitty.com wrote:
> > On Wednesday, February 21, 2018 at 9:14:41 PM UTC-6, Richard Damon wrote:
> >> On 2/21/18 5:59 PM, supercat@casperkitty.com wrote:
> >>> If there were recognized practical means of telling the compiler that
> >>> something weird was going on, it would make sense to deprecate code that
> >>> does weird things without telling the compiler. As yet, however, no such
> >>> means exist.
> >>>
> >>
> >> 'Something weird' in other words, I am going to break the rules and
> >> create undefined behavior, but I want you to do what I mean, not what
> >> the rules say you can.
> >
> > More like "I want the code compiled according to the semantics that
> > Dennis Ritchie invented in the 1970s, and which most compilers process
> > with optimizations disabled, but a compiler may make certain simplifying
> > assumptions when there's no particular evidence to suggest that they
> > won't hold.
> >
> > Consider the three functions:
> >
> > void weird1(float *p1, char *p2)
> > {
> > if (*p1) *p2|=1;
> > return *p1;
> > }
> > void weird2(float *p1, float *p2)
> > {
> > if (*p1) *(char*) p2|=1;
> > return *p1;
> > }
> > void weird3(float *p1, float *p2)
> > {
> > if (*p1) *(uint32_t*) p2|=1;
> > return *p1;
> > }
> >
> > A compiler could generate smaller code if it could assume that *p1 will
> > not be accessed by anything between the "if" and the "return". In the
> > absence of aliasing rules, would there be anything in any of those
> > functions that might suggest whether such an assumption would be likely
> > to cause trouble?
> >
>
> No, you mean I want it to work as I want to interpret the language that
> Dennis Ritchie invented in the 1970s, as maybe it happened to work on
> the particular implementation that I used, even if not define or
> required by that work.
>
> Give me a statement in K&R that says that the above code is 'valid',
> that accessing an object via a pointer to the wrong type (that isn't a
> char type) MUST do what you want.
>
> Note also, I believe that every (and certainly most)) implementation has
> a way to tell it to work the way you want, it just might not be the
> default way to execute it.
The 1974 C Reference Manual describes the behavior of pointer addition
operator as unconditionally multiplying an integer by the size of the
pointer's target type, and makes no mention of any cases being forbidden.
It doesn't say what should happen if an execution platform's pointer
arithmetic operations don't support a particular combination of operands,
but nor does it even remotely suggest that such issues should be relevant
for code which will never need to run on such platforms.
I don't have a copy of K&R handy, but the free() routine requires the
ability to take a *arbitraryType and perform computations on it which
would access storage that is not part of an array of arbitraryType.
While the malloc() and free() have as prerequisites the ability to receive
storage of suitable alignment from somewhere, K&R does not seem to have
regarded the ability to perform "interesting" pointer arithmetic as a
prerequisite worth mentioning.
While the Standard does not require that implementations be suitable for
systems programming (or any other purpose) I would not regard a dialect
that can't support systems programming as encapsulating the whole of a
language which was invented, in significant measure, for the purpose of
systems programming.
I've asked repeatedly for anything in C89 that would exempt arithmetic on
character pointers or pointers to storage received from malloc() from rules
that would--for any other kind of pointer--require that the storage addressed
by the pointer hold an actual object of array type. The simplest way to
resolve that on most platforms would be to say that the description of
pointer arithmetic as scaling the integer by the target type's size and
then adding that result to the address is applicable in all cases where
a region of storage would be capable of holding a suitable array of the
proper type satisfying any alignment or other restrictions, rather than
trying to say that the behavior is defined as described in some such
cases but not all.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-02-22 13:00 -0800 |
| Message-ID | <ln606oloy1.fsf@kst-u.example.com> |
| In reply to | #126993 |
supercat@casperkitty.com writes:
[...]
> I don't have a copy of K&R handy, but the free() routine requires the
> ability to take a *arbitraryType and perform computations on it which
> would access storage that is not part of an array of arbitraryType.
> While the malloc() and free() have as prerequisites the ability to receive
> storage of suitable alignment from somewhere, K&R does not seem to have
> regarded the ability to perform "interesting" pointer arithmetic as a
> prerequisite worth mentioning.
K&R1 discusses the free() function in the context of the UNIX system
interface, not as part of the standard library. It specifically
acknowledges that the code is system dependent.
[...]
> I've asked repeatedly for anything in C89 that would exempt arithmetic on
> character pointers or pointers to storage received from malloc() from rules
> that would--for any other kind of pointer--require that the storage addressed
> by the pointer hold an actual object of array type. The simplest way to
> resolve that on most platforms would be to say that the description of
> pointer arithmetic as scaling the integer by the target type's size and
> then adding that result to the address is applicable in all cases where
> a region of storage would be capable of holding a suitable array of the
> proper type satisfying any alignment or other restrictions, rather than
> trying to say that the behavior is defined as described in some such
> cases but not all.
Do you believe this is well defined in C89?
int main(void) {
struct {
int arr[2];
int after;
} obj;
obj.arr[2] = 42;
}
Would an implementation that traps at run time on the reference to
obj.arr[2] be non-conforming?
(I'm not assuming that obj.arr[2] occupies the same space as obj.after;
there could be padding between them.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-22 13:48 -0800 |
| Message-ID | <8a1a8466-c94e-46b3-b651-54b63fc8b114@googlegroups.com> |
| In reply to | #126994 |
On Thursday, February 22, 2018 at 3:00:57 PM UTC-6, Keith Thompson wrote:
> supercat@casperkitty.com writes:
> [...]
> > I don't have a copy of K&R handy, but the free() routine requires the
> > ability to take a *arbitraryType and perform computations on it which
> > would access storage that is not part of an array of arbitraryType.
> > While the malloc() and free() have as prerequisites the ability to receive
> > storage of suitable alignment from somewhere, K&R does not seem to have
> > regarded the ability to perform "interesting" pointer arithmetic as a
> > prerequisite worth mentioning.
>
> K&R1 discusses the free() function in the context of the UNIX system
> interface, not as part of the standard library. It specifically
> acknowledges that the code is system dependent.
It would seem odd for Ritchie to include code that he didn't expect to--at
minimum--be readily adaptable to a wide variety of implementations, nor
for him to point out any non-obvious ways in which the code might be non-
portable.
> > I've asked repeatedly for anything in C89 that would exempt arithmetic on
> > character pointers or pointers to storage received from malloc() from rules
> > that would--for any other kind of pointer--require that the storage addressed
> > by the pointer hold an actual object of array type. The simplest way to
> > resolve that on most platforms would be to say that the description of
> > pointer arithmetic as scaling the integer by the target type's size and
> > then adding that result to the address is applicable in all cases where
> > a region of storage would be capable of holding a suitable array of the
> > proper type satisfying any alignment or other restrictions, rather than
> > trying to say that the behavior is defined as described in some such
> > cases but not all.
>
> Do you believe this is well defined in C89?
>
> int main(void) {
> struct {
> int arr[2];
> int after;
> } obj;
> obj.arr[2] = 42;
> }
>
> Would an implementation that traps at run time on the reference to
> obj.arr[2] be non-conforming?
From what I can tell, it would be neither more nor less conforming than
one which would trap if code had done:
#include <stddef.h>
int main(void) {
struct s {
int arr[2];
int after;
} obj;
((char*)&obj)[offsetof(struct s, after)]=3;
}
I suspect that the authors of the Standard probably figured that it was
sufficiently obvious that the kind of pointer arithmetic in the second
example should work (defining offsetof(type,member) would be rather
pointless otherwise) that they didn't think it was necessary to actually
*say* so, but such an attitude would only be reasonable if one weren't
trying to mandate everything needed to make an implementation useful but
were instead merely focused on mandating things which one expected that
implementations would not otherwise provide.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2018-02-22 22:14 +0000 |
| Message-ID | <6hHjC.20913$gZ2.13125@fx23.iad> |
| In reply to | #126996 |
supercat@casperkitty.com writes: >On Thursday, February 22, 2018 at 3:00:57 PM UTC-6, Keith Thompson wrote: >> supercat@casperkitty.com writes: >> [...] >> > I don't have a copy of K&R handy, but the free() routine requires the >> > ability to take a *arbitraryType and perform computations on it which >> > would access storage that is not part of an array of arbitraryType. >> > While the malloc() and free() have as prerequisites the ability to receive >> > storage of suitable alignment from somewhere, K&R does not seem to have >> > regarded the ability to perform "interesting" pointer arithmetic as a >> > prerequisite worth mentioning. >> >> K&R1 discusses the free() function in the context of the UNIX system >> interface, not as part of the standard library. It specifically >> acknowledges that the code is system dependent. > >It would seem odd for Ritchie to include code that he didn't expect to--at >minimum--be readily adaptable to a wide variety of implementations, nor >for him to point out any non-obvious ways in which the code might be non- >portable. See, there you go imputing motive. Do note that the C compiler and run-time support facilities ran on the interdata 8/32[*] as well as the PDP-11, which in the 1970's was the epitome of portable. [*] Bell Labs chose the 8/32 for the port because it was as different from the PDP-11 as possible (see Byte, 8/1983, p 188 "The History of Unix"). 'Interdata 8/32 - the first port of unix' https://www.uow.edu.au/content/groups/public/@web/@inf/@scsse/documents/doc/uow103747.pdf > >I suspect that the authors of the Standard probably figured that it was Again, you impute motive.
[toc] | [prev] | [next] | [standalone]
Page 2 of 5 — ← Prev page 1 [2] 3 4 5 Next page →
Back to top | Article view | comp.lang.c
csiph-web