Ignore:
Timestamp:
Mar 9, 2024, 5:40:09 PM (21 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Children:
b64d0f4
Parents:
03606ce
Message:

switch to tabs, first attempt changing program-input style

Location:
doc/theses/mike_brooks_MMath/programs
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/mike_brooks_MMath/programs/bkgd-c-tyerr.c

    r03606ce r266732e  
    1010
    1111int main() {
     12        float * x;                      $\C{// x points at a floating-point number}$
     13        void (*y)(void);        $\C{// y points at a function}$
     14        @x = y;@                        $\C{// wrong}$
     15        @y = x;@                        $\C{// wrong}$
    1216
    13 /*
    14     These attempts to assign @y@ to @x@ and vice-versa are obviously ill-typed.
    15 */
    16     float * x;         // x points at a floating-point number
    17     void (*y)(void);   // y points at a function
    18                        ERR(
    19     x = y;             // wrong
    20     y = x;             // wrong
    21                        )
     17        float pi = 3.14;
     18        void f( void (*g)(void) ) { g(); }
     19        @f( &pi );@                     $\C{// wrong}$
     20}
    2221
    23 /*
    24     The first gets
    25         warning: assignment to `float *' from incompatible pointer type `void (*)(void)'
    26     and the second gets the opposite.
    27 
    28     Similarly,
    29 */
    30 
    31     float pi = 3.14;
    32     void f( void (*g)(void) ) {
    33         g();
    34     }
    35                        ERR(
    36     f( & pi );         // wrong
    37                        )
    38 /*
    39     gets
    40         warning: passing argument 1 of `f' from incompatible pointer type
    41     with a segmentation fault at runtime.
    42 
    43     That @f@'s attempt to call @g@ fails is not due to 3.14 being a particularly unlucky choice of value to put in the variable @pi@.
    44     Rather, it is because obtaining a program that includes this essential fragment, yet exhibits a behaviour other than "doomed to crash," is a matter for an obfuscated coding competition.
    45 
    46     A "tractable syntactic method for proving the absence of certain program behaviours
    47     by classifying phrases according to the kinds of values they compute"*1
    48     rejected the program.  The behaviour (whose absence is unprovable) is neither minor nor unlikely.
    49     The rejection shows that the program is ill-typed.
    50 
    51     Yet, the rejection presents as a GCC warning.
    52 
    53     In the discussion following, ``ill-typed'' means giving a nonzero @gcc -Werror@ exit condition with a message that discusses typing.
    54 
    55     *1  TAPL-pg1 definition of a type system
    56 */
    57 
    58 }
     22// Local Variables: //
     23// compile-command: "sed -f sedcmd bkgd-c-tyerr.c > tmp.c; gcc tmp.c" //
     24// End: //
  • doc/theses/mike_brooks_MMath/programs/bkgd-carray-arrty.c

    r03606ce r266732e  
    2424
    2525
    26     // SHOW(sizeof( a   ), "%zd");
    27     // SHOW(sizeof(&a   ), "%zd");
    28     // SHOW(sizeof( a[0]), "%zd");
    29     // SHOW(sizeof(&a[0]), "%zd");
     26        // SHOW(sizeof( a   ), "%zd");
     27        // SHOW(sizeof(&a   ), "%zd");
     28        // SHOW(sizeof( a[0]), "%zd");
     29        // SHOW(sizeof(&a[0]), "%zd");
    3030
    3131
    3232
    3333int main() {
     34        float a[10];
     35        static_assert(sizeof(float) == 4);              $\C{// floats (array elements) are 4 bytes}$
     36        static_assert(sizeof(void*) == 8);              $\C{// pointers are 8 bytes}$
     37        static_assert(sizeof(a) == 40);                 $\C{// array}$
     38        static_assert(sizeof(&a) == 8 );                $\C{// pointer to array}$
     39        static_assert(sizeof(a[0]) == 4 );              $\C{// first element}$
     40        static_assert(sizeof(&(a[0])) == 8 );   $\C{// pointer to first element}$
    3441
    35 /*
    36 When a programmer works with an array, C semantics provide access to a type that is different in every way from ``pointer to its first element.''
     42        typeof(&a) x;                                                   $\C{// x is pointer to array}$
     43        typeof(&(a[0])) y;                                              $\C{// y is pointer to first element}$
     44        @x = y;@                                                                $\C{// ill-typed}$
     45        @y = x;@                                                                $\C{// ill-typed}$
     46        static_assert(sizeof(typeof(a)) == 40);
     47        static_assert(sizeof(typeof(&a)) == 8 );
     48        static_assert(sizeof(typeof(a[0])) == 4 );
     49        static_assert(sizeof(typeof(&(a[0]))) == 8 );
    3750
    38 Its qualities become apparent by inspecting the declaration
    39 */
    40     float a[10];
    41 /*
     51        void f( float (*pa)[10] ) {
     52            static_assert(sizeof(   *pa     ) == 40); $\C{// array}$
     53            static_assert(sizeof(    pa     ) == 8 ); $\C{// pointer to array}$
     54            static_assert(sizeof(  (*pa)[0] ) == 4 ); $\C{// first element}$
     55            static_assert(sizeof(&((*pa)[0])) == 8 ); $\C{// pointer to first element}$
     56        }
     57        f( & a );
    4258
    43 The inspection begins by using @sizeof@ to provide definite program semantics for the intuition of an expression's type.
     59        float fs[] = {3.14, 1.707};
     60        char cs[] = "hello";
    4461
    45 Assuming a target platform keeps things concrete:
    46 */
    47     static_assert(sizeof(float)==4);    // floats (array elements) are 4 bytes
    48     static_assert(sizeof(void*)==8);    // pointers are 8 bytes
    49 /*
    50 
    51 Consider the sizes of expressions derived from @a@, modified by adding ``pointer to'' and ``first element'' (and including unnecessary parentheses to avoid confusion about precedence).
    52 */
    53     static_assert(sizeof(  a    ) == 40); // array
    54     static_assert(sizeof(& a    ) == 8 ); // pointer to array
    55     static_assert(sizeof(  a[0] ) == 4 ); // first element
    56     static_assert(sizeof(&(a[0])) == 8 ); // pointer to first element
    57 /*
    58 That @a@ takes up 40 bytes is common reasoning for C programmers.
    59 Set aside for a moment the claim that this first assertion is giving information about a type.
    60 For now, note that an array and a pointer to its first element are, sometimes, different things.
    61 
    62 The idea that there is such a thing as a pointer to an array may be surprising.
    63 It is not the same thing as a pointer to the first element:
    64 */
    65     typeof(& a    ) x;   // x is pointer to array
    66     typeof(&(a[0])) y;   // y is pointer to first element
    67                        ERR(
    68     x = y;             // ill-typed
    69     y = x;             // ill-typed
    70                        )
    71 /*
    72 The first gets
    73     warning: warning: assignment to `float (*)[10]' from incompatible pointer type `float *'
    74 and the second gets the opposite.
    75 */
    76 
    77 /*
    78 We now refute a concern that @sizeof(a)@ is reporting on special knowledge from @a@ being an local variable,
    79 say that it is informing about an allocation, rather than simply a type.
    80 
    81 First, recognizing that @sizeof@ has two forms, one operating on an expression, the other on a type, we observe that the original answers are unaffected by using the type-parameterized form:
    82 */
    83     static_assert(sizeof(typeof(  a    )) == 40);
    84     static_assert(sizeof(typeof(& a    )) == 8 );
    85     static_assert(sizeof(typeof(  a[0] )) == 4 );
    86     static_assert(sizeof(typeof(&(a[0]))) == 8 );
    87 
    88 /*
    89 Finally, the same sizing is reported when there is no allocation at all, and we launch the analysis instead from the pointer-to-array type.
    90 */
    91     void f( float (*pa)[10] ) {
    92         static_assert(sizeof(   *pa     ) == 40); // array
    93         static_assert(sizeof(    pa     ) == 8 ); // pointer to array
    94         static_assert(sizeof(  (*pa)[0] ) == 4 ); // first element
    95         static_assert(sizeof(&((*pa)[0])) == 8 ); // pointer to first element
    96     }
    97     f( & a );
    98 
    99 /*
    100 So, in spite of considerable programmer success enabled by an understanding that
    101 an array just a pointer to its first element (revisited TODO pointer decay),
    102 this understanding is simplistic.
    103 */
    104 
    105 /*
    106 A shortened form for declaring local variables exists, provided that length information is given in the initializer:
    107 */
    108     float fs[] = {3.14, 1.707};
    109     char cs[] = "hello";
    110 
    111     static_assert( sizeof(fs) == 2 * sizeof(float) );
    112     static_assert( sizeof(cs) == 6 * sizeof(char) );  // 5 letters + 1 null terminator
    113 
    114 /*
    115 In these declarations, the resulting types are both arrays, but their lengths are inferred.
    116 */
    117 
     62        static_assert( sizeof(fs) == 2 * sizeof(float) );
     63        static_assert( sizeof(cs) == 6 * sizeof(char) );  $\C{// 5 letters + 1 null terminator}$
    11864}
    11965
     66void syntaxReferenceCheck(void) {
     67        // $\rightarrow$ & (base element)
     68        //     & @float@
     69        //     & @float x;@
     70        //     & @[ float ]@
     71        //     & @[ float ]@
     72        float x0;
    12073
    121 void syntaxReferenceCheck(void) {
    122     // $\rightarrow$ & (base element)
    123     //     & @float@
    124     //     & @float x;@
    125     //     & @[ float ]@
    126     //     & @[ float ]@
    127     float x0;
     74        // $\rightarrow$ & pointer
     75        //     & @float *@
     76        //     & @float * x;@
     77        //     & @[ * float ]@
     78        //     & @[ * float ]@
     79        float * x1;
    12880
    129     // $\rightarrow$ & pointer
    130     //     & @float *@
    131     //     & @float * x;@
    132     //     & @[ * float ]@
    133     //     & @[ * float ]@
    134     float * x1;
     81        // $\rightarrow$ & array
     82        //     & @float[10]@
     83        //     & @float x[10];@
     84        //     & @[ [10] float ]@
     85        //     & @[ array(float, 10) ]@
     86        float x2[10];
    13587
    136     // $\rightarrow$ & array
    137     //     & @float[10]@
    138     //     & @float x[10];@
    139     //     & @[ [10] float ]@
    140     //     & @[ array(float, 10) ]@
    141     float x2[10];
     88        typeof(float[10]) x2b;
    14289
    143     typeof(float[10]) x2b;
    144 
    145     // & array of pointers
    146     //     & @(float*)[10]@
    147     //     & @float *x[10];@
    148     //     & @[ [10] * float ]@
    149     //     & @[ array(*float, 10) ]@
    150     float *x3[10];
     90        // & array of pointers
     91        //     & @(float*)[10]@
     92        //     & @float *x[10];@
     93        //     & @[ [10] * float ]@
     94        //     & @[ array(*float, 10) ]@
     95        float *x3[10];
    15196//    (float *)x3a[10];  NO
    15297
    153     // $\rightarrow$ & pointer to array
    154     //     & @float(*)[10]@
    155     //     & @float (*x)[10];@
    156     //     & @[ * [10] float ]@
    157     //     & @[ * array(float, 10) ]@
    158     float (*x4)[10];
     98        // $\rightarrow$ & pointer to array
     99        //     & @float(*)[10]@
     100        //     & @float (*x)[10];@
     101        //     & @[ * [10] float ]@
     102        //     & @[ * array(float, 10) ]@
     103        float (*x4)[10];
    159104
    160     // & pointer to array
    161     //     & @(float*)(*)[10]@
    162     //     & @float *(*x)[10];@
    163     //     & @[ * [10] * float ]@
    164     //     & @[ * array(*float, 10) ]@
    165     float *(*x5)[10];
    166     x5 =     (float*(*)[10]) x4;
     105        // & pointer to array
     106        //     & @(float*)(*)[10]@
     107        //     & @float *(*x)[10];@
     108        //     & @[ * [10] * float ]@
     109        //     & @[ * array(*float, 10) ]@
     110        float *(*x5)[10];
     111        x5 =     (float*(*)[10]) x4;
    167112//    x5 =     (float(*)[10]) x4;  // wrong target type; meta test suggesting above cast uses correct type
    168113
    169     // [here]
    170     // const
     114        // [here]
     115        // const
    171116
    172     // [later]
    173     // static
    174     // star as dimension
    175     // under pointer decay:                int p1[const 3]  being  int const *p1
     117        // [later]
     118        // static
     119        // star as dimension
     120        // under pointer decay:                int p1[const 3]  being  int const *p1
    176121
    177     const float * y1;
    178     float const * y2;
    179     float * const y3;
     122        const float * y1;
     123        float const * y2;
     124        float * const y3;
    180125
    181     y1 = 0;
    182     y2 = 0;
    183     // y3 = 0; // bad
     126        y1 = 0;
     127        y2 = 0;
     128        // y3 = 0; // bad
    184129
    185     // *y1 = 3.14; // bad
    186     // *y2 = 3.14; // bad
    187     *y3 = 3.14;
     130        // *y1 = 3.14; // bad
     131        // *y2 = 3.14; // bad
     132        *y3 = 3.14;
    188133
    189     const float z1 = 1.414;
    190     float const z2 = 1.414;
     134        const float z1 = 1.414;
     135        float const z2 = 1.414;
    191136
    192     // z1 = 3.14; // bad
    193     // z2 = 3.14; // bad
     137        // z1 = 3.14; // bad
     138        // z2 = 3.14; // bad
    194139
    195140
     
    199144void stx2() { const T x[10];
    200145//            x[5] = 3.14; // bad
    201             }
     146                }
    202147void stx3() { T const x[10];
    203148//            x[5] = 3.14; // bad
    204             }
     149                }
     150
     151// Local Variables: //
     152// compile-command: "sed -f sedcmd bkgd-carray-arrty.c > tmp.c; gcc tmp.c" //
     153// End: //
  • doc/theses/mike_brooks_MMath/programs/bkgd-carray-decay.c

    r03606ce r266732e  
    11#include <assert.h>
    22int main() {
     3        float a[10];                            $\C{// array}$
     4        float (*pa)[10] = &a;           $\C{// pointer to array}$
     5        float a0 = a[0];                        $\C{// element}$
     6        float *pa0 = &(a[0]);           $\C{// pointer to element}$
    37
    4 /*
    5 The last section established the difference between these four types:
    6 */
     8        float *pa0x = a;                        $\C{// (ok)}$
     9        assert( pa0 == pa0x );
     10        assert( sizeof(pa0x) != sizeof(a) );
    711
    8     float    a  [10] ;          // array
    9     float (*pa )[10] = & a    ; // pointer to array
    10     float    a0      =   a[0] ; // element
    11     float  *pa0      = &(a[0]); // pointer to element
     12        void f( float x[10], float *y ) {
     13                static_assert( sizeof(x) == sizeof(void*) );
     14                static_assert( sizeof(y) == sizeof(void*) );
     15        }
     16        f(0,0);
    1217
    13 /*
    14 But the expression used for obtaining the pointer to the first element is pedantic.
    15 The root of all C programmer experience with arrays is the shortcut
    16 */
    17     float  *pa0x     =   a    ; // (ok)
    18 /*
    19 which reproduces @pa0@, in type and value:
    20 */
    21     assert( pa0 == pa0x );
    22 /*
    23 The validity of this initialization is unsettling, in the context of the facts established in the last section.
    24 Notably, it initializes name @pa0x@ from expression @a@, when they are not of the same type:
    25 */
    26     assert( sizeof(pa0x) != sizeof(a) );
     18        // reusing local var `float a[10];`}
     19        float v;
     20        f(  a,  a ); $\C{// ok: two decays, one into an array spelling}$
     21        f( &v, &v ); $\C{// ok: no decays; a non-array passes to an array spelling}$
    2722
     23        char ca[] = "hello";    $\C{// array on stack, initialized from read-only data}$
     24        char *cp = "hello";     $\C{// pointer to read-only data [decay here]}$
     25        void edit(char c[]) {   $\C{// param is pointer}$
     26                c[3] = 'p';
     27        }
     28        edit(ca);               $\C{// ok [decay here]}$
     29        edit(cp);               $\C{// Segmentation fault}$
     30        edit("hello");          $\C{// Segmentation fault [decay here]}$
    2831
     32        void decay( float x[10] ) {
     33                static_assert( sizeof(x) == sizeof(void*) );
     34        }
     35        static_assert( sizeof(a) == 10 * sizeof(float) );
     36        decay(a);
    2937
     38        void no_decay( float (*px)[10] ) {
     39                static_assert( sizeof(*px) == 10 * sizeof(float) );
     40        }
     41        static_assert( sizeof(*pa) == 10 * sizeof(float) );
     42        no_decay(pa);
     43}
    3044
    31 
    32 
    33 
    34 
    35 
    36 
    37 
    38 
    39 
    40     void f( float x[10], float *y ) {
    41         static_assert( sizeof(x) == sizeof(void*) );
    42         static_assert( sizeof(y) == sizeof(void*) );
    43     }
    44     f(0,0);
    45 
    46 
    47 
    48 
    49 
    50 
    51 
    52 
    53 
    54 
    55 
    56 
    57 
    58 
    59 
    60     // reusing local var `float a[10];`
    61     float v;
    62     f(  a,  a ); // ok: two decays, one into an array spelling
    63     f( &v, &v ); // ok: no decays; a non-array passes to an array spelling
    64 
    65 
    66 
    67 
    68 
    69 
    70 
    71 
    72 
    73 
    74 
    75 
    76 
    77 
    78 
    79 
    80     char ca[] = "hello";    // array on stack, initialized from read-only data
    81     char *cp = "hello";     // pointer to read-only data [decay here]
    82     void edit(char c[]) {   // param is pointer
    83         c[3] = 'p';
    84     }
    85     edit(ca);               // ok [decay here]
    86     edit(cp);               // Segmentation fault
    87     edit("hello");          // Segmentation fault [decay here]
    88 
    89 
    90 
    91 
    92 
    93 
    94 
    95 
    96 
    97 
    98 
    99 
    100     void decay( float x[10] ) {
    101         static_assert( sizeof(x) == sizeof(void*) );
    102     }
    103     static_assert( sizeof(a) == 10 * sizeof(float) );
    104     decay(a);
    105 
    106     void no_decay( float (*px)[10] ) {
    107         static_assert( sizeof(*px) == 10 * sizeof(float) );
    108     }
    109     static_assert( sizeof(*pa) == 10 * sizeof(float) );
    110     no_decay(pa);
    111 }
     45// Local Variables: //
     46// compile-command: "sed -f sedcmd bkgd-carray-decay.c > tmp.c; gcc tmp.c" //
     47// End: //
Note: See TracChangeset for help on using the changeset viewer.