// File: iZhangHui[P]CppPrimer/CH03_StringsVectorsAndArrays/examples/multidim.cc
// Function: main
int main()
{
	// array of size 3; each element is an array of 4 uninitailzed ints 
	int ia1[3][4];
	
	// array of size 10; each element is a 20-element array 
	// whose elements are arrays of 30 ints
	int arr[10][20][30] = {0}; // initialize all elements to 0
	
	// assigns the first element of arr to the last element 
	// in the last row of ia
	ia1[2][3] = arr[0][0][0];
	
	// binds row to the second four-element array in ia 
	int (&row)[4] = ia1[1];
	
	// three elements, each element is an array of size 4
	int ia2[3][4] = { 
	    {0, 1, 2, 3},   // initializers for the row indexed by 0
	    {4, 5, 6, 7},   // initializers for the row indexed by 1
	    {8, 9, 10, 11}  // initializers for the row indexed by 2
	};
	
	// equivalent initialization without the optional 
	// nested braces for each row
	int ia3[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
	
	// explicitly initialize only element 0 in each row
	int ia4[3][4] = {{ 0 }, { 4 }, { 8 }};
	
	// explicitly initialize row 0; the remaining elements 
	// are value initialized
	int ix[3][4] = {0, 3, 6, 9};
	
	// prints 9 0 0 
	cout << ix[0][3] << ' ' << ix[1][0] << ' ' << ix[2][0] << endl;
	
	constexpr size_t rowCnt = 3, colCnt = 4;
	int ia[rowCnt][colCnt];   // 12 uninitialized elements 
	
    // for each row
    for (size_t i = 0; i != rowCnt; ++i) {
        // for each column within the row
        for (size_t j = 0; j != colCnt; ++j) {
            // assign the element's positional index as its value
            ia[i][j] = i * colCnt + j;   
		}
	}

	// four ways to print the contents of ia
	// 1. using nested range for loops
	for (const auto &row : ia) // for every element in the outer array
		for (auto col : row)   // for every element in the inner array
			cout << col << endl; // print the element's value
    cout << ia[0][0] << ' ' << ia[2][3] << endl; // prints 0 11


	// 2. using pointers and a traditional for loop
	//    with pointer arithmetic to calculate the end pointers 
	for (auto p = ia; p != ia + rowCnt; ++p) {
		// q points to the first element of an array of four ints; 
		// that is, q points to an int
	    for (auto q = *p; q != *p + colCnt; ++q)
	         cout << *q << ' ';
		cout << endl;
	}
	
	// 3. using pointers and a traditional for loop
	//    with the library begin and end functions to manage the pointers
	for (auto p = begin(ia); p != end(ia); ++p) {
		// q points to the first element in an inner array
		for (auto q = begin(*p); q != end(*p); ++q)
			cout << *q << ' ';  // prints the int value to which q points
		cout << endl;
	}
	
	// 4. using a type alias to declare the loop control variable
	using int_array = int[4]; // new style type alias declaration 

	for (int_array *p = ia; p != ia + 3; ++p) {
	    for (int *q = *p; q != *p + 4; ++q)
	         cout << *q << ' ';
		cout << endl;
	}

	// alternative way to assign positional index to elements 
	// in a two-dimensional array
	int alt_ia[rowCnt][colCnt]; // 12 uninitialized elements 
	size_t cnt = 0;
	for (auto &row : alt_ia)    // for every element in the outer array
		for (auto &col : row) { // for every element in the inner array
			col = cnt;          // give this element the next value
			++cnt;              // increment cnt
		}
	// now print the value of the array
	for (const auto &row : alt_ia) // for every element in the outer array
		for (auto col : row)     // for every element in the inner array
			cout << col << endl;

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x6060, %rsp           # imm = 0x6060
movl $0x0, -0x4(%rbp)
leaq -0x5e00(%rbp), %rdi
xorl %esi, %esi
movl $0x5dc0, %edx           # imm = 0x5DC0
callq 0x1030
movl -0x5e00(%rbp), %eax
movl %eax, -0x14(%rbp)
leaq -0x40(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x5e08(%rbp)
leaq -0x5e40(%rbp), %rdi
leaq 0xde5(%rip), %rsi       # 0x2010
movl $0x30, %edx
callq 0x1040
leaq -0x5e70(%rbp), %rdi
leaq 0xdfd(%rip), %rsi       # 0x2040
movl $0x30, %edx
callq 0x1040
leaq -0x5ea0(%rbp), %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0x1030
movl $0x4, -0x5e90(%rbp)
movl $0x8, -0x5e80(%rbp)
leaq -0x5ed0(%rbp), %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0x1030
movl $0x3, -0x5ecc(%rbp)
movl $0x6, -0x5ec8(%rbp)
movl $0x9, -0x5ec4(%rbp)
movl -0x5ec4(%rbp), %esi
movq 0x2d26(%rip), %rdi      # 0x3fd8
callq 0x1090
movq %rax, %rdi
movl $0x20, %esi
callq 0x1070
movq %rax, %rdi
movl -0x5ec0(%rbp), %esi
callq 0x1090
movq %rax, %rdi
movl $0x20, %esi
callq 0x1070
movq %rax, %rdi
movl -0x5eb0(%rbp), %esi
callq 0x1090
movq %rax, %rdi
movq 0x2cd1(%rip), %rsi      # 0x3fc8
callq 0x1060
movq $0x3, -0x5ed8(%rbp)
movq $0x4, -0x5ee0(%rbp)
movq $0x0, -0x5f18(%rbp)
cmpq $0x3, -0x5f18(%rbp)
je 0x1399
movq $0x0, -0x5f20(%rbp)
cmpq $0x4, -0x5f20(%rbp)
je 0x1383
movq -0x5f18(%rbp), %rax
shlq $0x2, %rax
addq -0x5f20(%rbp), %rax
movl %eax, %edx
movq -0x5f18(%rbp), %rcx
leaq -0x5f10(%rbp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
movq -0x5f20(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x5f20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x5f20(%rbp)
jmp 0x1332
jmp 0x1385
movq -0x5f18(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x5f18(%rbp)
jmp 0x131d
leaq -0x5f10(%rbp), %rax
movq %rax, -0x5f28(%rbp)
movq -0x5f28(%rbp), %rax
movq %rax, -0x5f30(%rbp)
movq -0x5f28(%rbp), %rax
addq $0x30, %rax
movq %rax, -0x5f38(%rbp)
movq -0x5f30(%rbp), %rax
cmpq -0x5f38(%rbp), %rax
je 0x1484
movq -0x5f30(%rbp), %rax
movq %rax, -0x5f40(%rbp)
movq -0x5f40(%rbp), %rax
movq %rax, -0x5f48(%rbp)
movq -0x5f48(%rbp), %rax
movq %rax, -0x5f50(%rbp)
movq -0x5f48(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x5f58(%rbp)
movq -0x5f50(%rbp), %rax
cmpq -0x5f58(%rbp), %rax
je 0x146b
movq -0x5f50(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x5f5c(%rbp)
movl -0x5f5c(%rbp), %esi
movq 0x2b95(%rip), %rdi      # 0x3fd8
callq 0x1090
movq %rax, %rdi
movq 0x2b76(%rip), %rsi      # 0x3fc8
callq 0x1060
movq -0x5f50(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x5f50(%rbp)
jmp 0x1417
jmp 0x146d
movq -0x5f30(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x5f30(%rbp)
jmp 0x13c7
movl -0x5f10(%rbp), %esi
movq 0x2b47(%rip), %rdi      # 0x3fd8
callq 0x1090
movq %rax, %rdi
movl $0x20, %esi
callq 0x1070
movq %rax, %rdi
movl -0x5ee4(%rbp), %esi
callq 0x1090
movq %rax, %rdi
movq 0x2b0d(%rip), %rsi      # 0x3fc8
callq 0x1060
leaq -0x5f10(%rbp), %rax
movq %rax, -0x5f68(%rbp)
movq -0x5f68(%rbp), %rax
leaq -0x5f10(%rbp), %rcx
addq $0x30, %rcx
cmpq %rcx, %rax
je 0x156e
movq -0x5f68(%rbp), %rax
movq %rax, -0x5f70(%rbp)
movq -0x5f70(%rbp), %rax
movq -0x5f68(%rbp), %rcx
addq $0x10, %rcx
cmpq %rcx, %rax
je 0x1544
movq -0x5f70(%rbp), %rax
movl (%rax), %esi
movq 0x2aba(%rip), %rdi      # 0x3fd8
callq 0x1090
movq %rax, %rdi
movl $0x20, %esi
callq 0x1070
movq -0x5f70(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x5f70(%rbp)
jmp 0x14f7
movq 0x2a8d(%rip), %rdi      # 0x3fd8
movq 0x2a76(%rip), %rsi      # 0x3fc8
callq 0x1060
movq -0x5f68(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x5f68(%rbp)
jmp 0x14ce
leaq -0x5f10(%rbp), %rdi
callq 0x18f0
movq %rax, -0x5f78(%rbp)
movq -0x5f78(%rbp), %rax
movq %rax, -0x6050(%rbp)
leaq -0x5f10(%rbp), %rdi
callq 0x1900
movq %rax, %rcx
movq -0x6050(%rbp), %rax
cmpq %rcx, %rax
je 0x164a
movq -0x5f78(%rbp), %rdi
callq 0x1920
movq %rax, -0x5f80(%rbp)
movq -0x5f80(%rbp), %rax
movq %rax, -0x6058(%rbp)
movq -0x5f78(%rbp), %rdi
callq 0x1930
movq %rax, %rcx
movq -0x6058(%rbp), %rax
cmpq %rcx, %rax
je 0x1620
movq -0x5f80(%rbp), %rax
movl (%rax), %esi
movq 0x29de(%rip), %rdi      # 0x3fd8
callq 0x1090
movq %rax, %rdi
movl $0x20, %esi
callq 0x1070
movq -0x5f80(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x5f80(%rbp)
jmp 0x15c1
movq 0x29b1(%rip), %rdi      # 0x3fd8
movq 0x299a(%rip), %rsi      # 0x3fc8
callq 0x1060
movq -0x5f78(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x5f78(%rbp)
jmp 0x1581
leaq -0x5f10(%rbp), %rax
movq %rax, -0x5f88(%rbp)
movq -0x5f88(%rbp), %rax
leaq -0x5f10(%rbp), %rcx
addq $0x30, %rcx
cmpq %rcx, %rax
je 0x16f8
movq -0x5f88(%rbp), %rax
movq %rax, -0x5f90(%rbp)
movq -0x5f90(%rbp), %rax
movq -0x5f88(%rbp), %rcx
addq $0x10, %rcx
cmpq %rcx, %rax
je 0x16ce
movq -0x5f90(%rbp), %rax
movl (%rax), %esi
movq 0x2930(%rip), %rdi      # 0x3fd8
callq 0x1090
movq %rax, %rdi
movl $0x20, %esi
callq 0x1070
movq -0x5f90(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x5f90(%rbp)
jmp 0x1681
movq 0x2903(%rip), %rdi      # 0x3fd8
movq 0x28ec(%rip), %rsi      # 0x3fc8
callq 0x1060
movq -0x5f88(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x5f88(%rbp)
jmp 0x1658
movq $0x0, -0x5fc8(%rbp)
leaq -0x5fc0(%rbp), %rax
movq %rax, -0x5fd0(%rbp)
movq -0x5fd0(%rbp), %rax
movq %rax, -0x5fd8(%rbp)
movq -0x5fd0(%rbp), %rax
addq $0x30, %rax
movq %rax, -0x5fe0(%rbp)
movq -0x5fd8(%rbp), %rax
cmpq -0x5fe0(%rbp), %rax
je 0x17f0
movq -0x5fd8(%rbp), %rax
movq %rax, -0x5fe8(%rbp)
movq -0x5fe8(%rbp), %rax
movq %rax, -0x5ff0(%rbp)
movq -0x5ff0(%rbp), %rax
movq %rax, -0x5ff8(%rbp)
movq -0x5ff0(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x6000(%rbp)
movq -0x5ff8(%rbp), %rax
cmpq -0x6000(%rbp), %rax
je 0x17d7
movq -0x5ff8(%rbp), %rax
movq %rax, -0x6008(%rbp)
movq -0x5fc8(%rbp), %rax
movl %eax, %ecx
movq -0x6008(%rbp), %rax
movl %ecx, (%rax)
movq -0x5fc8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x5fc8(%rbp)
movq -0x5ff8(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x5ff8(%rbp)
jmp 0x1781
jmp 0x17d9
movq -0x5fd8(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x5fd8(%rbp)
jmp 0x1731
leaq -0x5fc0(%rbp), %rax
movq %rax, -0x6010(%rbp)
movq -0x6010(%rbp), %rax
movq %rax, -0x6018(%rbp)
movq -0x6010(%rbp), %rax
addq $0x30, %rax
movq %rax, -0x6020(%rbp)
movq -0x6018(%rbp), %rax
cmpq -0x6020(%rbp), %rax
je 0x18db
movq -0x6018(%rbp), %rax
movq %rax, -0x6028(%rbp)
movq -0x6028(%rbp), %rax
movq %rax, -0x6030(%rbp)
movq -0x6030(%rbp), %rax
movq %rax, -0x6038(%rbp)
movq -0x6030(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x6040(%rbp)
movq -0x6038(%rbp), %rax
cmpq -0x6040(%rbp), %rax
je 0x18c2
movq -0x6038(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x6044(%rbp)
movl -0x6044(%rbp), %esi
movq 0x273e(%rip), %rdi      # 0x3fd8
callq 0x1090
movq %rax, %rdi
movq 0x271f(%rip), %rsi      # 0x3fc8
callq 0x1060
movq -0x6038(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x6038(%rbp)
jmp 0x186e
jmp 0x18c4
movq -0x6018(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x6018(%rbp)
jmp 0x181e
xorl %eax, %eax
addq $0x6060, %rsp           # imm = 0x6060
popq %rbp
retq
nopw %cs:(%rax,%rax)