| [7972603] | 1 | #include <assert.h>
 | 
|---|
 | 2 | int main() {
 | 
|---|
 | 3 | 
 | 
|---|
 | 4 | /*
 | 
|---|
 | 5 | The last section established the difference between these four types:
 | 
|---|
 | 6 | */
 | 
|---|
 | 7 | 
 | 
|---|
 | 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 | 
 | 
|---|
 | 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) );
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | 
 | 
|---|
 | 29 | 
 | 
|---|
 | 30 | 
 | 
|---|
 | 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 | }
 | 
|---|