#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

#define SHOW(x, fmt) printf( #x ": " fmt "\n", x )

#ifdef ERRS
#define ERR(...) __VA_ARGS__
#else
#define ERR(...)
#endif

// int main( int argc, const char *argv[] ) {
//     assert(argc == 2);
//     const int n = atoi(argv[1]);
//     assert(0 < n && n < 1000);

//     float a1[42];
//     float a2[n];
//     SHOW(sizeof(a1), "%zd");
//     SHOW(sizeof(a2), "%zd");

// }


	// SHOW(sizeof( a   ), "%zd");
	// SHOW(sizeof(&a   ), "%zd");
	// SHOW(sizeof( a[0]), "%zd");
	// SHOW(sizeof(&a[0]), "%zd");



int main() {
	float ar[10];
	static_assert( sizeof(float) == 4 );	$\C{// floats (array elements) are 4 bytes}$
	static_assert( sizeof(void *) == 8 );	$\C{// pointers are 8 bytes}$
	static_assert( sizeof(ar) == 40 );		$\C{// array}$
	static_assert( sizeof(&ar) == 8 );		$\C{// pointer to array}$
	static_assert( sizeof(ar[0]) == 4 );	$\C{// first element}$
	static_assert( sizeof(&(ar[0])) == 8 );	$\C{// pointer to first element}$

	typeof(&ar) x = &ar;					$\C{// x is pointer to array}$
	typeof(&(ar[0])) y = &ar[0];			$\C{// y is pointer to first element}$
	@x = y;@								$\C{// ill-typed}$
	@y = x;@								$\C{// ill-typed}$
	static_assert( sizeof(typeof(ar)) == 40 ); $\C{// array}$
	static_assert( sizeof(typeof(&ar)) == 8 );	$\C{// pointer to array}$
	static_assert( sizeof(typeof(ar[0])) == 4 ); $\C{// first element}$
	static_assert( sizeof(typeof(&(ar[0]))) == 8 ); $\C{// pointer to first element}$

	void f( float (*pa)[10] ) {
		static_assert( sizeof( *pa ) == 40 ); $\C{// array}$
		static_assert( sizeof( pa ) == 8 ); $\C{// pointer to array}$
		static_assert( sizeof( (*pa)[0] ) == 4 ); $\C{// first element}$
		static_assert( sizeof(&((*pa)[0])) == 8 ); $\C{// pointer to first element}$
	}
	f( &ar );

	float fs@[]@ = {3.14, 1.77};
	char cs@[]@ = "hello";					// shorthand for { 'h', 'e', 'l', 'l', 'o', '\0' }
	static_assert( sizeof(fs) == 2 * sizeof(float) );
	static_assert( sizeof(cs) == 6 * sizeof(char) );  $\C{// 5 letters + 1 null terminator}$

	float fm[]@[2]@ = { {3.14, 1.77}, {12.4, 0.01}, {7.8, 1.23} };  $\C{// brackets define structuring}$
	char cm[]@[sizeof("hello")]@ = { "hello", "hello", "hello" };
	static_assert( sizeof(fm) == 3 * 2 * sizeof(float) );
	static_assert( sizeof(cm) == 3 * 6 * sizeof(char) );
}

void syntaxReferenceCheck(void) {
	// $\rightarrow$ & (base element)
	//     & @float@ 
	//     & @float x;@ 
	//     & @[ float ]@
	//     & @[ float ]@
	float x0;

	// $\rightarrow$ & pointer
	//     & @float *@ 
	//     & @float * x;@ 
	//     & @[ * float ]@
	//     & @[ * float ]@
	float * x1;

	// $\rightarrow$ & array 
	//     & @float[10]@ 
	//     & @float x[10];@ 
	//     & @[ [10] float ]@
	//     & @[ array(float, 10) ]@
	float x2[10];

	typeof(float[10]) x2b;

	// & array of pointers
	//     & @(float*)[10]@
	//     & @float *x[10];@
	//     & @[ [10] * float ]@
	//     & @[ array(*float, 10) ]@
	float *x3[10];
//    (float *)x3a[10];  NO

	// $\rightarrow$ & pointer to array
	//     & @float(*)[10]@
	//     & @float (*x)[10];@
	//     & @[ * [10] float ]@
	//     & @[ * array(float, 10) ]@
	float (*x4)[10];

	// & pointer to array
	//     & @(float*)(*)[10]@
	//     & @float *(*x)[10];@
	//     & @[ * [10] * float ]@
	//     & @[ * array(*float, 10) ]@
	float *(*x5)[10];
	x5 =     (float*(*)[10]) x4;
//    x5 =     (float(*)[10]) x4;  // wrong target type; meta test suggesting above cast uses correct type

	// [here]
	// const

	// [later]
	// static
	// star as dimension
	// under pointer decay:                int p1[const 3]  being  int const *p1

	const float * y1;
	float const * y2;
	float * const y3;

	y1 = 0;
	y2 = 0;
	// y3 = 0; // bad

	// *y1 = 3.14; // bad
	// *y2 = 3.14; // bad
	*y3 = 3.14;

	const float z1 = 1.414;
	float const z2 = 1.414;

	// z1 = 3.14; // bad
	// z2 = 3.14; // bad


}

#define T float
void stx2() { const T x[10];
//            x[5] = 3.14; // bad
}
void stx3() { T const x[10];
//            x[5] = 3.14; // bad
}

// Local Variables: //
// compile-command: "sed -f sedcmd bkgd-carray-arrty.c | gcc-11 -Wall -Wextra -x c -" //
// End: //
