Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #126772 > unrolled thread

Opinion sought: Is this strictly conforming C?

Started bylee@ansync.com
First post2018-02-15 17:20 -0800
Last post2018-02-26 10:17 -0800
Articles 20 on this page of 83 — 14 participants

Back to article view | Back to comp.lang.c


Contents

  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 1 of 5  [1] 2 3 4 5  Next page →


#126772 — Opinion sought: Is this strictly conforming C?

Fromlee@ansync.com
Date2018-02-15 17:20 -0800
SubjectOpinion sought: Is this strictly conforming C?
Message-ID<e054cddb-6cb6-46d3-805a-db0733421bed@googlegroups.com>
I am involved in a debate on StackOverflow about whether this code, which accesses the same chunk of memory as both a 1D and 2D array, is strictly conforming, well-defined C with no undefined behavior:

----

#include <stdio.h> 

int a1[100]; 
int (*a2)[10] = (int (*)[10])a1; 

int main(int argc, char *argv[]) { 
        for (int i = 0; i < 100; i += 1) a1[i] = i + 1; 

        for (int i = 0; i < 10; i += 1) { 
                for (int j = 0; j < 10; j += 1) { 
                        printf("%2d ", a2[i][j]); 
                } 
                printf("\n"); 
        } 
}

[toc] | [next] | [standalone]


#126775

FromJames Kuyper <jameskuyper@verizon.net>
Date2018-02-15 22:15 -0500
Message-ID<p65ibn$par$1@dont-email.me>
In reply to#126772
On 02/15/2018 08:20 PM, lee@ansync.com wrote:
> I am involved in a debate on StackOverflow about whether this code,
> which accesses the same chunk of memory as both a 1D and 2D array, is
> strictly conforming, well-defined C with no undefined behavior:
> 
> ----
> 
> #include <stdio.h> 
> 
> int a1[100]; 
> int (*a2)[10] = (int (*)[10])a1;

In this context, a1 is implicitly converted into a pointer to the first
element of a1. Here's what the standard has to say about the conversion
of a pointer to int into a pointer to int[10]:
"If the resulting pointer is not correctly aligned 68) for the
referenced type, the behavior is undefined. Otherwise, when converted
back again, the result shall compare equal to the original pointer. When
a pointer to an object is converted to a pointer to a character type,
the result points to the lowest addressed byte of the object. Successive
increments of the result, up to the size of the object, yield pointers
to the remaining bytes of the object." (6.3.2.3p7).

It's permissible for an object of type 'int[10]' to have stricter
alignment requirements than an object of type int[100], but it's not at
all likely. As a practical matter, we can ignore that issue - but as far
as the standard is concerned, it is a possible problem. Using C2011,
it's possible to check for that possibility using the _Alignof() feature.

However, there's a much more important problem, and one which is so
subtle that it might be hard to notice. It's about what the standard
doesn't say, which is much harder to notice than what it does say. The
ONLY thing the standard says about the result of the conversion is that
it can be reversed. Since int[10] is not a character type, that clause
does doesn't tell you anything else that you can do with the resulting
pointer. Note, in particular, that it doesn't bother telling you what,
if anything, the resulting pointer points at. What happens when you do
anything to such a pointer other than converting it back to it's
original type is undefined behavior, by "omission of any explicit
definition of the behavior" (4p2).

This interpretation of the words of the standard tends to be
controversial, primarily because code like this will, in fact, generally
work as you may have mistakenly thought it was guaranteed to work. That
fact can make it very hard for people to accept that it is not, in fact,
guaranteed to work.

> int main(int argc, char *argv[]) { 
>         for (int i = 0; i < 100; i += 1) a1[i] = i + 1; 
> 
>         for (int i = 0; i < 10; i += 1) { 
>                 for (int j = 0; j < 10; j += 1) { 
>                         printf("%2d ", a2[i][j]); 
>                 } 
>                 printf("\n"); 
>         } 
> }

[toc] | [prev] | [next] | [standalone]


#126804

Fromsupercat@casperkitty.com
Date2018-02-16 08:44 -0800
Message-ID<29e38fdf-86ef-4935-891a-b2683ee99b88@googlegroups.com>
In reply to#126775
On Thursday, February 15, 2018 at 9:15:12 PM UTC-6, James Kuyper wrote:
> This interpretation of the words of the standard tends to be
> controversial, primarily because code like this will, in fact, generally
> work as you may have mistakenly thought it was guaranteed to work. That
> fact can make it very hard for people to accept that it is not, in fact,
> guaranteed to work.

What makes this particularly nasty is that such code had a clear meaning
going back to 1974, the stated purpose of the Standard was not to invent
a new language but describe an existing one, and nothing in the Standard
indicates any intention to change or deprecate the existing behavior.

C99 changed some rules from C89, and I think the purpose was to facilitate
optimizations which could best be accomplished by specifying that use of
the [] operator on an lvalue of array type does *not* decompose it into a
pointer, but invites a compiler to assume the lvalue expression will not
be used to access anything other than an element of the same array.  An
additional assumption which they might have also wanted to allow, but which
is not presently justifiable under the Standard, would be that elements of
different arrays can only alias if the indices match.

[toc] | [prev] | [next] | [standalone]


#126809

Fromjameskuyper@verizon.net
Date2018-02-16 11:47 -0800
Message-ID<62935351-8f39-4b92-9d19-8660933cc7fa@googlegroups.com>
In reply to#126804
On Friday, February 16, 2018 at 11:45:07 AM UTC-5, supe...@casperkitty.com wrote:
> On Thursday, February 15, 2018 at 9:15:12 PM UTC-6, James Kuyper wrote:
> > This interpretation of the words of the standard tends to be
> > controversial, primarily because code like this will, in fact, generally
> > work as you may have mistakenly thought it was guaranteed to work. That
> > fact can make it very hard for people to accept that it is not, in fact,
> > guaranteed to work.
> 
> What makes this particularly nasty is that such code had a clear meaning
> going back to 1974, the stated purpose of the Standard was not to invent
> a new language but describe an existing one,

Where is this purpose stated? My understanding was that their purpose
was to standardize the language, not describe it, and as such they were
not only allowed, but expected, to make a few changes during the process
of standardizing it. The C standard describes the language more
precisely than K&R C did, and as a side-effect, it necessarily describes
a somewhat different language.
At the time of the first standard, C was not a single monolithic
language, it was a different language for each compiler. Many of those
languages were incompatible with each other to varying degrees.

The committee could, and did, endorse the existence of a variety of
different existing implementations, by making the behavior of various
constructs unspecified, implementation-defined, or undefined. However,
it also sometimes addressed that variety by endorsing only one
particular option, rendering any implementation that did not choose that
option non-conforming - this was also permitted by the committee's
charter.



> ... and nothing in the Standard
> indicates any intention to change or deprecate the existing behavior.

Note: K&R C said: 
"A pointer to one type may be converted to a pointer to another type.
The resulting pointer may cause addressing exceptions upon use if the
subject pointer does not refer to an object suitably aligned in storage.
It is guaranteed that a pointer to an object of a given size may be
converted to a pointer to an object of a smaller size and back again
without change."

There's no such clause in my copy of C89, which surprised me. C99 says:
"A pointer to an object or incomplete type may be converted to a pointer
to a different object or incomplete type. If the resulting pointer is not
correctly aligned 57) for the pointed-to type, the behavior is undefined.
Otherwise, when converted back again, the result shall compare equal to
the original pointer. When a pointer to an object is converted to a
pointer to a character type, the result points to the lowest addressed
byte of the object. Successive increments of the result, up to the size
of the object, yield pointers to the remaining bytes of the object.
A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare equal
to the original pointer. If a converted pointer is used to call a
function whose type is not compatible with the pointed-to type, the
behavior is undefined."

Key differences between K&R and C99:
K&R apparently allowed conversions between pointers to object types and
pointer to function types; C99 only allows conversions within each
category. In K&R, the reversibility guarantee applied only if the
intermediate type was small; in C99 alignment issues are the only
barrier to reversibility. K&R said "without change", whereas C99 says
"shall compare equal", which allows for the possibility of pointers with
different representations that compare equal with each other, a feature
of many real systems. C99 gives special status to conversions to
pointers to character types.

However, For conversions from a pointer to an object type to a pointer
to a different non-character type, neither K&R C, nor any version of
the standard, defines where the resulting pointer points, nor do they
specify anything that you can do with the result other than converting
it back to the original type. That doesn't constitute a change from K&R
C, and is the basis for my claim that the behavior is undefined.

C90, forward:
>    The need for a single clearly defined standard had arisen in the C
> community due to a rapidly expanding use of the C programming language
> and the variety of differing translator implementations that had been
> and were being developed.  The existence of similar but incompatible
> implementations was a serious problem for program developers who
> wished to develop code that would compile and execute as expected in
> several different environments.

That paragraph makes it clear that, prior to the standard, C was not a
single coherent language, but a wide variety of incompatible languages.

>    Part of this problem could be traced to the fact that implementors
> did not have an adequate definition of the C language upon which to
> base their implementations.  The de facto C programming language
> standard, The C Programming Language by Brian W. Kernighan and Dennis
> M. Ritchie, is an excellent book; however, it is not precise or
> complete enough to specify the C language fully.  In addition, the

This part makes it clear that they felt a need to change things that K&R
had not been sufficiently clear about.

> language has grown over years of use to incorporate new ideas in
> programming and to address some of the weaknesses of the original
> language.

This makes it clear that they felt that there were worthwhile new ideas
to be incorporated, and weakness that needed be addressed.

>   American National Standard Programming Language C addresses the
> problems of both the program developer and the translator implementor
> by specifying the C language precisely.

This reiterates the point that they felt the language needed to be
specified more precisely than it was by K&R. What's not entirely clear
from this forward is the fact that they decided to be more precise, not
only about what your could rely upon when writing C code, but also about
what you could NOT rely upon.

[toc] | [prev] | [next] | [standalone]


#126813

Fromsupercat@casperkitty.com
Date2018-02-16 13:00 -0800
Message-ID<447d580a-fec5-4fcf-8e3b-a80384984556@googlegroups.com>
In reply to#126809
On Friday, February 16, 2018 at 1:47:18 PM UTC-6, james...@verizon.net wrote:
> On Friday, February 16, 2018 at 11:45:07 AM UTC-5, supe...@casperkitty.com wrote:
> > What makes this particularly nasty is that such code had a clear meaning
> > going back to 1974, the stated purpose of the Standard was not to invent
> > a new language but describe an existing one,
> 
> Where is this purpose stated? My understanding was that their purpose
> was to standardize the language, not describe it, and as such they were
> not only allowed, but expected, to make a few changes during the process
> of standardizing it. The C standard describes the language more
> precisely than K&R C did, and as a side-effect, it necessarily describes
> a somewhat different language.

From the foreword to C89:

   A concerted effort was made to codify existing practice wherever
   unambiguous and consistent practice could be identified.

From the C89 Rationale:

    Existing code is important, existing implementations are not. 

> At the time of the first standard, C was not a single monolithic
> language, it was a different language for each compiler. Many of those
> languages were incompatible with each other to varying degrees.
> 
> The committee could, and did, endorse the existence of a variety of
> different existing implementations, by making the behavior of various
> constructs unspecified, implementation-defined, or undefined. However,
> it also sometimes addressed that variety by endorsing only one
> particular option, rendering any implementation that did not choose that
> option non-conforming - this was also permitted by the committee's
> charter.

The Rationale does note a few places where the Standard mandates that
some constructs be processed in a fashion inconsistent with the way some
existing code might require.  For example, some existing compilers which
were given:

    unsigned char a=1,b=2;
    unsigned char c=a-b > 0;

would have performed the subtraction using either unsigned char or unsigned
int even on platforms where char was smaller than int.  The rationale calls
out such changes and offers explicit justification for them.  I find it
implausible that the authors of the Standard would have intended to remove
features from the language which were universally supported and widely relied
upon without making any mention of such intention nor offering any
justification for it.

> > ... and nothing in the Standard
> > indicates any intention to change or deprecate the existing behavior.
> 
> Note: K&R C said: 
> "A pointer to one type may be converted to a pointer to another type.
> The resulting pointer may cause addressing exceptions upon use if the
> subject pointer does not refer to an object suitably aligned in storage.
> It is guaranteed that a pointer to an object of a given size may be
> converted to a pointer to an object of a smaller size and back again
> without change."
> 
> There's no such clause in my copy of C89, which surprised me. C99 says:
> "A pointer to an object or incomplete type may be converted to a pointer
> to a different object or incomplete type. If the resulting pointer is not
> correctly aligned 57) for the pointed-to type, the behavior is undefined.
> Otherwise, when converted back again, the result shall compare equal to
> the original pointer. When a pointer to an object is converted to a
> pointer to a character type, the result points to the lowest addressed
> byte of the object. Successive increments of the result, up to the size
> of the object, yield pointers to the remaining bytes of the object.
> A pointer to a function of one type may be converted to a pointer to a
> function of another type and back again; the result shall compare equal
> to the original pointer. If a converted pointer is used to call a
> function whose type is not compatible with the pointed-to type, the
> behavior is undefined."
> 
> Key differences between K&R and C99:
> K&R apparently allowed conversions between pointers to object types and
> pointer to function types; C99 only allows conversions within each
> category. In K&R, the reversibility guarantee applied only if the
> intermediate type was small; in C99 alignment issues are the only
> barrier to reversibility. K&R said "without change", whereas C99 says
> "shall compare equal", which allows for the possibility of pointers with
> different representations that compare equal with each other, a feature
> of many real systems. C99 gives special status to conversions to
> pointers to character types.

On many implementations, there would be some unsigned integer type T such
that if p1 is a pointer of any type, p and (T)p will be represented by the
same bit pattern.  Further, on many platforms, pointer arithmetic and
integer arithmetic are isomorphic within any region of allocated storage,
if not globally.  The language intended to be usable on platforms where
pointers are handled differently, and implementations for such platforms
were clearly not required to support code which relied upon such details.
I don't think there was ever any intention, though, to suggest that
implementations for linear-address machines shouldn't support semantics
beyond those that target machines with more unusual addressing schemes.

> However, For conversions from a pointer to an object type to a pointer
> to a different non-character type, neither K&R C, nor any version of
> the standard, defines where the resulting pointer points, nor do they
> specify anything that you can do with the result other than converting
> it back to the original type. That doesn't constitute a change from K&R
> C, and is the basis for my claim that the behavior is undefined.

K&R specifies that objects are stored in sequences of consecutive bytes
in memory; given a pointer T *p, p identifies the location of the first
byte occupied by *p.  Those facts together suffice to fully describe the
behavior of reading and writing different pointers in every situation
where the number of possible values of T equals the number of possible
bit patterns in the underlying storage.

> C90, forward:
> >    The need for a single clearly defined standard had arisen in the C
> > community due to a rapidly expanding use of the C programming language
> > and the variety of differing translator implementations that had been
> > and were being developed.  The existence of similar but incompatible
> > implementations was a serious problem for program developers who
> > wished to develop code that would compile and execute as expected in
> > several different environments.
> 
> That paragraph makes it clear that, prior to the standard, C was not a
> single coherent language, but a wide variety of incompatible languages.

Indeed, C has never been a single coherent language.  Given that different
platforms have different features, and different programs have different
needs, the only way a single language could be implementable on most
platforms while fulfilling most needs would be by accepting that it will
not be possible for all implementations to support all useful programs.

On the other hand, there are many things which implementations prior to
the Standard had processed in consistent fashion.  I don't think the
authors of were particularly interested in trying to enumerate them;
they were more interested in addressing places where implementations had
diverged.

It would have been helpful if the authors of the C Standard had overcome
any political opposition to recognizing more categories of implementations.
While it would be useful to have dialects of C that are suitable for use on
ones'-complement or sign-magnitude systems, weird sizes of "char", segmented
memory architectures, etc. such things should not have distracted from the
fact that hardware platforms evolving toward similar lines.  The majority of
implementations that weren't for 8086 or 80286 (which had a particular style
of unusual pointers) were for platforms that were--from a C perspective--
identical except for the size of "int", the size of pointers, and endian-
ness.  Too bad the authors of the Standard were never willing to acknowledge
that.

[toc] | [prev] | [next] | [standalone]


#126862

FromTim Rentsch <txr@alumni.caltech.edu>
Date2018-02-19 12:25 -0800
Message-ID<kfnfu5wwwun.fsf@x-alumni2.alumni.caltech.edu>
In reply to#126804
supercat@casperkitty.com writes:

> C99 changed some rules from C89, [...]

What changes are those?  Specifically, which sections and
paragraphs in the two Standards are you talking about?
If you don't cite specific sections and paragraphs, along
with a statement of what change you think was made in each
case, you're just blowing smoke.

[toc] | [prev] | [next] | [standalone]


#126863

Fromsupercat@casperkitty.com
Date2018-02-19 13:21 -0800
Message-ID<42bf72ce-89a8-405e-9155-9fbebe4b6d31@googlegroups.com>
In reply to#126862
On Monday, February 19, 2018 at 2:25:29 PM UTC-6, Tim Rentsch wrote:
> supercat@casperkitty.com writes:
> 
> > C99 changed some rules from C89, [...]
> 
> What changes are those?  Specifically, which sections and
> paragraphs in the two Standards are you talking about?
> If you don't cite specific sections and paragraphs, along
> with a statement of what change you think was made in each
> case, you're just blowing smoke.

From N1570 Annex J.2:

    -- An array subscript is out of range, even if an object is
       apparently accessible with the given subscript (as in the
       lvalue expression a[1][7] given the declaration int a[4][5])
       (6.5.6).
 
I don't recall anything in C89 that would have implied that pointer
arithmetic would only be usable within an *inner* array object; indeed,
the biggest benefit to requiring that arrays not have padding between
rows is that such guarantee would allow multi-dimensional arrays to be
treated like flat arrays when needed.

[toc] | [prev] | [next] | [standalone]


#126864

FromRandy Howard <rhoward.mx@EverybodyUsesIt.com>
Date2018-02-19 15:26 -0600
Message-ID<p6ffd6$ldc$1@gioia.aioe.org>
In reply to#126863
On 2/19/18 3:21 PM, supercat@casperkitty.com wrote:
> On Monday, February 19, 2018 at 2:25:29 PM UTC-6, Tim Rentsch wrote:
>> supercat@casperkitty.com writes:
>>
>>> C99 changed some rules from C89, [...]
>>
>> What changes are those?  Specifically, which sections and
>> paragraphs in the two Standards are you talking about?
>> If you don't cite specific sections and paragraphs, along
>> with a statement of what change you think was made in each
>> case, you're just blowing smoke.
> 
>  From N1570 Annex J.2:
> 
>      -- An array subscript is out of range, even if an object is
>         apparently accessible with the given subscript (as in the
>         lvalue expression a[1][7] given the declaration int a[4][5])
>         (6.5.6).
>   
> I don't recall anything in C89 that would have implied that pointer
> arithmetic would only be usable within an *inner* array object; indeed,
> the biggest benefit to requiring that arrays not have padding between
> rows is that such guarantee would allow multi-dimensional arrays to be
> treated like flat arrays when needed.
> 

The main thing the committee seems to have accomplished over the years 
is making sure that nobody can possibly trust themselves to wade through 
all the new minefields of UB that are added. Strange how nobody was 
scared of writing code before ANSI and ISO weighed in on the problem.

Also, they did a bang up job of making sure that nobody should ever 
trust threads or the broken concurrency model defined in C11.

-- 
Randy Howard
(replace the obvious text in the obvious way if you wish to contact me 
directly)

[toc] | [prev] | [next] | [standalone]


#126865

FromKeith Thompson <kst-u@mib.org>
Date2018-02-19 13:59 -0800
Message-ID<lnd110od3i.fsf@kst-u.example.com>
In reply to#126863
supercat@casperkitty.com writes:
> On Monday, February 19, 2018 at 2:25:29 PM UTC-6, Tim Rentsch wrote:
>> supercat@casperkitty.com writes:
>> 
>> > C99 changed some rules from C89, [...]
>> 
>> What changes are those?  Specifically, which sections and
>> paragraphs in the two Standards are you talking about?
>> If you don't cite specific sections and paragraphs, along
>> with a statement of what change you think was made in each
>> case, you're just blowing smoke.
>
> From N1570 Annex J.2:
>
>     -- An array subscript is out of range, even if an object is
>        apparently accessible with the given subscript (as in the
>        lvalue expression a[1][7] given the declaration int a[4][5])
>        (6.5.6).
>  
> I don't recall anything in C89 that would have implied that pointer
> arithmetic would only be usable within an *inner* array object; indeed,
> the biggest benefit to requiring that arrays not have padding between
> rows is that such guarantee would allow multi-dimensional arrays to be
> treated like flat arrays when needed.

The C89/C90 definition of pointer addition is similar to the current
definition.

    If both the pointer operand and the result point to elements
    of the same array object, or one past the last element of the
    array object, the evaluation shall not produce an overflow;
    otherwise, the behavior is undefined.

In the example in N1570, we have:
    int a[4][5];
    a[1][7];

For a[1][7] to be valid, you'd have to have an array object of at
least 8 int elements.

I think (correct me if I'm mistaken) that you're assuming the
declaration of a creates an object of type int[20].  Can you cite
wording in the C89/C90 standard that supports this assumption?

-- 
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]


#126866

Fromsupercat@casperkitty.com
Date2018-02-19 14:38 -0800
Message-ID<fd094d02-819b-42f5-9f97-89587ef3bf00@googlegroups.com>
In reply to#126865
On Monday, February 19, 2018 at 3:59:29 PM UTC-6, Keith Thompson wrote:
> In the example in N1570, we have:
>     int a[4][5];
>     a[1][7];
> 
> For a[1][7] to be valid, you'd have to have an array object of at
> least 8 int elements.
> 
> I think (correct me if I'm mistaken) that you're assuming the
> declaration of a creates an object of type int[20].  Can you cite
> wording in the C89/C90 standard that supports this assumption?

Consider the example from "3.3.2.1 Array subscripting" of C89, which
describes multi-dimensional array subscripting in terms of multiplying
the outer index by the length of the row.  That would suggest a memory
model in which a multi-dimensional array is, and can be treated as, a
single sequence of inner values.

Note also that the ability to use a "char*" to access objects of arbitrary
type as though they were a single char[] has always been fundamental to C,
and there is nothing I can see that would suggest that the ability to
"flatten" types should be limited to accesses via type "char*".

[toc] | [prev] | [next] | [standalone]


#126868

FromKeith Thompson <kst-u@mib.org>
Date2018-02-19 15:21 -0800
Message-ID<ln8tboo9an.fsf@kst-u.example.com>
In reply to#126866
supercat@casperkitty.com writes:
> On Monday, February 19, 2018 at 3:59:29 PM UTC-6, Keith Thompson wrote:
>> In the example in N1570, we have:
>>     int a[4][5];
>>     a[1][7];
>> 
>> For a[1][7] to be valid, you'd have to have an array object of at
>> least 8 int elements.
>> 
>> I think (correct me if I'm mistaken) that you're assuming the
>> declaration of a creates an object of type int[20].  Can you cite
>> wording in the C89/C90 standard that supports this assumption?
>
> Consider the example from "3.3.2.1 Array subscripting" of C89, which
> describes multi-dimensional array subscripting in terms of multiplying
> the outer index by the length of the row.  That would suggest a memory
> model in which a multi-dimensional array is, and can be treated as, a
> single sequence of inner values.

I don't think it suggests it very strongly.

Quoting "ansi.c.txt", a draft of C89 (because it's easier to
copy-and-paste from it than from my copy of C90):

    Consider the array object defined by the declaration 

         int x[3][5];

    Here x is a 3x5 array of int s; more precisely, x is an array of
    three member objects, each of which is an array of five int s.
    In the expression x[i] , which is equivalent to (*(x+(i))) ,
    x is first converted to a pointer to the initial array of five
    int s.  Then i is adjusted according to the type of x , which
    conceptually entails multiplying i by the size of the object to
    which the pointer points, namely an array of five int objects.
    The results are added and indirection is applied to yield
    an array of five int s.  When used in the expression x[i][j] ,
    that in turn is converted to a pointer to the first of the
    int s, so x[i][j] yields an int.

The restrictions on pointer addition (which I cited and you snipped)
still apply, even if a given addition might "conceptually" seem valid.

> Note also that the ability to use a "char*" to access objects of arbitrary
> type as though they were a single char[] has always been fundamental to C,
> and there is nothing I can see that would suggest that the ability to
> "flatten" types should be limited to accesses via type "char*".

Sure, it's obviously valid if you assume that it's valid.

Upthread, you cited N1570 Annex J.2, which says that a[1][7] has
undefined behavior.  Annex J is informative, not normative, which
means that if the behavior is undefined, it should follow from the
normative wording in 6.5.6 (Additive operators).  Has the normative
definition of pointer addition changed from C89 to C11 in a way
that would cause a[1][7] to be defined in C89 and undefined in C11?
(I suggest that C89 didn't define the behavior, and C11 has made
that more explicit.)

-- 
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]


#126870

Fromsupercat@casperkitty.com
Date2018-02-19 15:59 -0800
Message-ID<b250f55e-7ce4-469c-961c-98d549f83abd@googlegroups.com>
In reply to#126868
On Monday, February 19, 2018 at 5:21:34 PM UTC-6, Keith Thompson wrote:
> supercat@casperkitty.com writes:
> > On Monday, February 19, 2018 at 3:59:29 PM UTC-6, Keith Thompson wrote:
> >> In the example in N1570, we have:
> >>     int a[4][5];
> >>     a[1][7];
> >> 
> >> For a[1][7] to be valid, you'd have to have an array object of at
> >> least 8 int elements.
> >> 
> >> I think (correct me if I'm mistaken) that you're assuming the
> >> declaration of a creates an object of type int[20].  Can you cite
> >> wording in the C89/C90 standard that supports this assumption?
> >
> > Consider the example from "3.3.2.1 Array subscripting" of C89, which
> > describes multi-dimensional array subscripting in terms of multiplying
> > the outer index by the length of the row.  That would suggest a memory
> > model in which a multi-dimensional array is, and can be treated as, a
> > single sequence of inner values.
> 
> I don't think it suggests it very strongly.
> 
> Quoting "ansi.c.txt", a draft of C89 (because it's easier to
> copy-and-paste from it than from my copy of C90):
> 
>     Consider the array object defined by the declaration 
> 
>          int x[3][5];
> 
>     Here x is a 3x5 array of int s; more precisely, x is an array of
>     three member objects, each of which is an array of five int s.
>     In the expression x[i] , which is equivalent to (*(x+(i))) ,
>     x is first converted to a pointer to the initial array of five
>     int s.  Then i is adjusted according to the type of x , which
>     conceptually entails multiplying i by the size of the object to
>     which the pointer points, namely an array of five int objects.
>     The results are added and indirection is applied to yield
>     an array of five int s.  When used in the expression x[i][j] ,
>     that in turn is converted to a pointer to the first of the
>     int s, so x[i][j] yields an int.

I read the Standard as suggesting that given T *p, p[i] is equivalent to
*((T*)((char*)p + i*(int)sizeof(T))), at least in cases where
"i*(int)sizeof(T)" would fit in an "int".  I see nothing that would
suggest that p[i] would not behave the same way as the latter expression
in all such cases.

Further, the C89 Standard does not recognize the possibility that two
pointers may have the same type and value but not be equivalent.  Does
anything in the Standard suggest the existences of cases where (p+x)+y
would be defined, and where computation of x+y neither overflows nor
"wraps", but where the behavior of p+(x+y) would not be defined equivalent
to (p+x)+y?  Given int a[4][5], I think it's unambiguous that
arr[1]+5==arr[2].  Would that not imply that arr[1]+(5+2) is equivalent
to (arr[1]+5)+2, which is in turn equivalent to arr[2]+2?

> The restrictions on pointer addition (which I cited and you snipped)
> still apply, even if a given addition might "conceptually" seem valid.

Why describe things in such terms if code can't actually do such
multiplication and addition itself?

> > Note also that the ability to use a "char*" to access objects of arbitrary
> > type as though they were a single char[] has always been fundamental to C,
> > and there is nothing I can see that would suggest that the ability to
> > "flatten" types should be limited to accesses via type "char*".
> 
> Sure, it's obviously valid if you assume that it's valid.
> 
> Upthread, you cited N1570 Annex J.2, which says that a[1][7] has
> undefined behavior.  Annex J is informative, not normative, which
> means that if the behavior is undefined, it should follow from the
> normative wording in 6.5.6 (Additive operators).  Has the normative
> definition of pointer addition changed from C89 to C11 in a way
> that would cause a[1][7] to be defined in C89 and undefined in C11?
> (I suggest that C89 didn't define the behavior, and C11 has made
> that more explicit.)

Perhaps the behavior is defined by the normative part of the Standard and
Annex J errs in suggesting that it isn't, but Annex J strongly suggests that
the Standard should be read as binding pointer arithmetic to the inner
object even though that would be a major restriction compared with K&R,
with which the Committee claims it was trying to be compatible.

The authors of C89 weren't trying to mandate absolutely everything that
should be expected of a useful implementation.  They expected that people
writing compilers would be familiar with K&R, and would attempt to support
constructs described therein when practical whether they were ordered to
or not.  When the easiest way of upholding the Standard wouldn't require a
compiler to know or care about certain things, and where extant compilers
simply ignored those things, the authors of the Standard generally didn't
bother specifying that those things should in fact have no effect.

[toc] | [prev] | [next] | [standalone]


#126872

FromKeith Thompson <kst-u@mib.org>
Date2018-02-19 17:11 -0800
Message-ID<ln4lmco479.fsf@kst-u.example.com>
In reply to#126870
supercat@casperkitty.com writes:
> On Monday, February 19, 2018 at 5:21:34 PM UTC-6, Keith Thompson wrote:
>> supercat@casperkitty.com writes:
>> > On Monday, February 19, 2018 at 3:59:29 PM UTC-6, Keith Thompson wrote:
>> >> In the example in N1570, we have:
>> >>     int a[4][5];
>> >>     a[1][7];
>> >> 
>> >> For a[1][7] to be valid, you'd have to have an array object of at
>> >> least 8 int elements.
>> >> 
>> >> I think (correct me if I'm mistaken) that you're assuming the
>> >> declaration of a creates an object of type int[20].  Can you cite
>> >> wording in the C89/C90 standard that supports this assumption?
>> >
>> > Consider the example from "3.3.2.1 Array subscripting" of C89, which
>> > describes multi-dimensional array subscripting in terms of multiplying
>> > the outer index by the length of the row.  That would suggest a memory
>> > model in which a multi-dimensional array is, and can be treated as, a
>> > single sequence of inner values.
>> 
>> I don't think it suggests it very strongly.
>> 
>> Quoting "ansi.c.txt", a draft of C89 (because it's easier to
>> copy-and-paste from it than from my copy of C90):
>> 
>>     Consider the array object defined by the declaration 
>> 
>>          int x[3][5];
>> 
>>     Here x is a 3x5 array of int s; more precisely, x is an array of
>>     three member objects, each of which is an array of five int s.
>>     In the expression x[i] , which is equivalent to (*(x+(i))) ,
>>     x is first converted to a pointer to the initial array of five
>>     int s.  Then i is adjusted according to the type of x , which
>>     conceptually entails multiplying i by the size of the object to
>>     which the pointer points, namely an array of five int objects.
>>     The results are added and indirection is applied to yield
>>     an array of five int s.  When used in the expression x[i][j] ,
>>     that in turn is converted to a pointer to the first of the
>>     int s, so x[i][j] yields an int.
>
> I read the Standard as suggesting that given T *p, p[i] is equivalent to
> *((T*)((char*)p + i*(int)sizeof(T))), at least in cases where
> "i*(int)sizeof(T)" would fit in an "int".  I see nothing that would
> suggest that p[i] would not behave the same way as the latter expression
> in all such cases.

I have no idea why you added the extraneous (int) cast.

> Further, the C89 Standard does not recognize the possibility that two
> pointers may have the same type and value but not be equivalent.  Does
> anything in the Standard suggest the existences of cases where (p+x)+y
> would be defined, and where computation of x+y neither overflows nor
> "wraps", but where the behavior of p+(x+y) would not be defined equivalent
> to (p+x)+y?  Given int a[4][5], I think it's unambiguous that
> arr[1]+5==arr[2].  Would that not imply that arr[1]+(5+2) is equivalent
> to (arr[1]+5)+2, which is in turn equivalent to arr[2]+2?
>
>> The restrictions on pointer addition (which I cited and you snipped)
>> still apply, even if a given addition might "conceptually" seem valid.
>
> Why describe things in such terms if code can't actually do such
> multiplication and addition itself?

I think the word "conceptually" answers your question.  The phrase
"which conceptually entails multiplying i by the size of the object to
which the pointer points" is intended, I think, as a metaphor to help
the reader understand what's going on.  It's not intended to suggest
that a C multiplication operator is evaluated.

The normative definition of pointer arithmetic does not refer to
multiplication.

The restrictions on pointer arithmetic are not conceptual or implied.
Pointer addition explicitly has undefined behavior if the result doesn't
point to an element of the relevant array object or just past its end.

If a[1][7] is valid in C89, what array object of at least 8 elements
does it refer to?

[snip]

> The authors of C89 weren't trying to mandate absolutely everything that
> should be expected of a useful implementation.  They expected that people
> writing compilers would be familiar with K&R, and would attempt to support
> constructs described therein when practical whether they were ordered to
> or not.  When the easiest way of upholding the Standard wouldn't require a
> compiler to know or care about certain things, and where extant compilers
> simply ignored those things, the authors of the Standard generally didn't
> bother specifying that those things should in fact have no effect.

What normative wording changed between C89 and C11 that made a[1][7]
undefined?

-- 
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]


#126877

FromDavid Brown <david.brown@hesbynett.no>
Date2018-02-20 09:17 +0100
Message-ID<p6glj4$jro$1@dont-email.me>
In reply to#126870
On 20/02/18 00:59, supercat@casperkitty.com wrote:

<snip>

>  I see nothing that would
> suggest that p[i] would not behave the same way as the latter expression
> in all such cases.
> 

A great many of your arguments are of this form.  To me, it shows you
have a fundamental misunderstanding of what a language standard - and
the C standards in particular - actually are.  The C standards give a
set of defined behaviour - anything they do not describe is undefined
behaviour.  That is what the phrase "undefined behaviour" /means/ - it
is behaviour that is not defined in the standard.

So if you "see nothing that would allow a particular behaviour", then
that behaviour is undefined (assuming you have read everything in the
document).  And if you "see nothing that would prevent a particular
behaviour", then it means /absolutely nothing/.

For a simple, clear-cut example, the standard says that unsigned
arithmetic uses modular wraparound for overflow.  "I see nothing in the
standard that prevents signed arithmetic using the same behaviour" -
that is absolutely true, and absolutely irrelevant.  As the standard
does not say explicitly that signed arithmetic overflow works this way,
the behaviour of signed arithmetic overflow is undefined behaviour.  At
best, this sort of "I see nothing" argument shows that a compiler /may/
choose to implement behaviour like that without being non-conforming.

So please, every time you try to argue about C from the "I see nothing"
standpoint, understand that your point is almost certainly, well, pointless.

[toc] | [prev] | [next] | [standalone]


#126884

Fromsupercat@casperkitty.com
Date2018-02-20 07:58 -0800
Message-ID<f5234659-1e2c-4e92-b16f-3068786a5f30@googlegroups.com>
In reply to#126877
On Tuesday, February 20, 2018 at 2:17:55 AM UTC-6, David Brown wrote:
> On 20/02/18 00:59, supercat@casperkitty.com wrote:
> 
> <snip>
> 
> >  I see nothing that would
> > suggest that p[i] would not behave the same way as the latter expression
> > in all such cases.
> > 
> 
> A great many of your arguments are of this form.  To me, it shows you
> have a fundamental misunderstanding of what a language standard - and
> the C standards in particular - actually are.  The C standards give a
> set of defined behaviour - anything they do not describe is undefined
> behaviour.  That is what the phrase "undefined behaviour" /means/ - it
> is behaviour that is not defined in the standard.

The authors of the C language standard have never, to date, sought to fully
define everything that should be expected of a useful C implementation.  If
one were to judge C89 or its successors the same way as one would evaluate
other language standards, they would be recognized as describing a silly and
useless language.  The only way in which they can be remotely useful is if
they are regarded as a baseline which must be augmented to make
implementations usable for most purposes.

Which is more plausible:

  1. When the authors said "conceptually" multiply, they were suggesting that
     on platforms with unusual addressing schemes, the method of computing
     addresses might not actual multiplication by the size of things.  They
     thought the fact that the behavior should be defined the same way as
     existing implementations had been doing it was so obvious that they
     didn't need to waste ink saying so.

  2. When the authors said "conceptually" mutltiply, they intended that
     programmers should only be able to rely upon a fraction of the cases
     where behavior had to date been defined by the extremely vast majority
     of implementations--including 100% of implementations that most people
     would ever encounter.

If the authors had intended to disallow behaviors that had been consistently
processed by nearly all C implementations to date, can you think of any
reason they didn't explicitly say so?

> So if you "see nothing that would allow a particular behaviour", then
> that behaviour is undefined (assuming you have read everything in the
> document).  And if you "see nothing that would prevent a particular
> behaviour", then it means /absolutely nothing/.

Do you think that the authors of the C Standard were intending to describe
the existing language, or define a new language which removes certain useful
features for no articulable reason?

In cases where a behavior had been unambiguously defined by the existing
language, and nobody had articulated any reason not to support it, would the
language standard be made more or less useful by suggesting that quality
implementations should be expected to support the behavior unless they
document a compelling reason for doing otherwise, or by suggesting that any
programmer who wants to use the behavior must read through the documentation
of every single compiler they use to confirm that the author isn't deciding
to do something wonky for the fun of it.

> For a simple, clear-cut example, the standard says that unsigned
> arithmetic uses modular wraparound for overflow.  "I see nothing in the
> standard that prevents signed arithmetic using the same behaviour" -
> that is absolutely true, and absolutely irrelevant.  As the standard
> does not say explicitly that signed arithmetic overflow works this way,
> the behaviour of signed arithmetic overflow is undefined behaviour.  At
> best, this sort of "I see nothing" argument shows that a compiler /may/
> choose to implement behaviour like that without being non-conforming.

The Standard allows low-quality implementations to do a lot of things, and
even goes so far as to explicitly say that an implementation could be
conforming and yet be of such low quality as to be useless.  No program can
be reasonably expected to run usefully on all possible conforming
implementations, and the fact that a *conforming* implementation might do
something stupid doesn't mean that high-quality implementations that are
suitable for any particular purposes could do so (since doing so might make
implementations unsuitable for such purpose).

[toc] | [prev] | [next] | [standalone]


#126896

FromDavid Brown <david.brown@hesbynett.no>
Date2018-02-20 18:21 +0100
Message-ID<p6hlej$66v$1@dont-email.me>
In reply to#126884
On 20/02/18 16:58, supercat@casperkitty.com wrote:
> On Tuesday, February 20, 2018 at 2:17:55 AM UTC-6, David Brown wrote:
>> On 20/02/18 00:59, supercat@casperkitty.com wrote:
>>
>> <snip>
>>

> Which is more plausible:
> 
That's another of your favourite phrases, and again usually indicates a 
misunderstanding or false dichotomy.

Which is more plausible:

1. The moon is made of green cheese.

2. Supercat is the author of a book on Java programming, and has 
infiltrated comp.lang.c with the intention of sowing FUD about C so that 
we will all switch to Java programming and buy his book.


Personally, I think the most plausible explanation of your thinking is 
that you have decided in advance what you think C is supposed to be, and 
are trying desperately to rationalise it after the fact.


<https://en.wikipedia.org/wiki/List_of_fallacies>

I am not sure whether your "I see nothing to suggest..." arguments count 
as "Argument from ignorance" or "Argument from incredulity" - you'd have 
to ask our resident self-proclaimed philosopher Fir on that one.  "False 
dichotomy" is on that list, and you can look up "Circular reasoning" too.


Or you can keep arguing against what is written in the standards - maybe 
with enough wishful thinking you will change the way C works.

[toc] | [prev] | [next] | [standalone]


#126898

FromKeith Thompson <kst-u@mib.org>
Date2018-02-20 09:25 -0800
Message-ID<lnsh9vmv35.fsf@kst-u.example.com>
In reply to#126884
supercat@casperkitty.com writes:
[...]
> Which is more plausible:
>
>   1. When the authors said "conceptually" multiply, they were suggesting that
>      on platforms with unusual addressing schemes, the method of computing
>      addresses might not actual multiplication by the size of things.  They
>      thought the fact that the behavior should be defined the same way as
>      existing implementations had been doing it was so obvious that they
>      didn't need to waste ink saying so.
>
>   2. When the authors said "conceptually" mutltiply, they intended that
>      programmers should only be able to rely upon a fraction of the cases
>      where behavior had to date been defined by the extremely vast majority
>      of implementations--including 100% of implementations that most people
>      would ever encounter.

The context of the phrase '"conceptually" multiply' is a passage in the
C89/C90 standard discussing array indexing.  Here it is (quoting from
ansi.c.txt, a pre-C89 draft), since you keep snipping it.

    Example

       Consider the array object defined by the declaration

         int x[3][5];

    Here x is a 3x5 array of int s; more precisely, x is an array of
    three member objects, each of which is an array of five int s.
    In the expression x[i] , which is equivalent to (*(x+(i))) ,
    x is first converted to a pointer to the initial array of five
    int s.  Then i is adjusted according to the type of x , which
    conceptually entails multiplying i by the size of the object to
    which the pointer points, namely an array of five int objects.
    The results are added and indirection is applied to yield
    an array of five int s.  When used in the expression x[i][j],
    that in turn is converted to a pointer to the first of the
    int s, so x[i][j] yields an int.

3. When the authors said "conceptually" multiply, they were giving an
   informal statement (in a non-normative example) about how pointer
   arithmetic works.  The multiplication is not a C multiplication
   operation.  It's *conceptual*.  This informal description does not
   override the normative definition of pointer arithmetic, which does
   not refer to multiplication.

> If the authors had intended to disallow behaviors that had been consistently
> processed by nearly all C implementations to date, can you think of any
> reason they didn't explicitly say so?

Since the behavior in question (evaluating, for example, x[1][7])
is undefined, no behavior is being disallowed.  Any conforming
implementation is perfectly free to treat x[1][7] in exactly the
way you think it should.

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;

[snip]

-- 
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]


#126907

Fromsupercat@casperkitty.com
Date2018-02-20 11:52 -0800
Message-ID<2dc98694-34c7-4c1a-ac2d-8b82ca95369e@googlegroups.com>
In reply to#126898
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*.

[toc] | [prev] | [next] | [standalone]


#126913

FromRichard Damon <Richard@Damon-Family.org>
Date2018-02-20 22:27 -0500
Message-ID<BG5jC.57834$9z2.31034@fx43.iad>
In reply to#126907
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. 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.

[toc] | [prev] | [next] | [standalone]


#126915

Fromsupercat@casperkitty.com
Date2018-02-20 23:07 -0800
Message-ID<ec78cf65-4533-46eb-96cf-d056c989765c@googlegroups.com>
In reply to#126913
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 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]


Page 1 of 5  [1] 2 3 4 5  Next page →

Back to top | Article view | comp.lang.c


csiph-web