void main() {
  int a[3][4] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23};
  printf("%d,%d\n", a, *a);
  printf("%d,%d\n", a[0], *(a + 0));
  printf("%d,%d\n", &a[0], &a[0][0]);
  printf("%d,%d\n", a[1], a + 1);
  printf("%d,%d\n", &a[1][0], *(a + 1) + 0);
  printf("%d,%d\n", a[2], *(a + 2));
  printf("%d,%d\n", &a[2], a + 2);
  printf("%d,%d\n", a[1][0], *(*(a + 1) + 0));
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
lea    -0x30(%rbp),%rdi
lea    0xecd(%rip),%rsi
mov    $0x30,%edx
call   1040 <memcpy@plt>
lea    -0x30(%rbp),%rsi
lea    -0x30(%rbp),%rdx
lea    0xee4(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x30(%rbp),%rsi
lea    -0x30(%rbp),%rdx
lea    0xece(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x30(%rbp),%rsi
lea    -0x30(%rbp),%rdx
lea    0xeb8(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x30(%rbp),%rsi
add    $0x10,%rsi
lea    -0x30(%rbp),%rdx
add    $0x10,%rdx
lea    0xe9a(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x30(%rbp),%rsi
add    $0x10,%rsi
lea    -0x30(%rbp),%rdx
add    $0x10,%rdx
lea    0xe7c(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x30(%rbp),%rsi
add    $0x20,%rsi
lea    -0x30(%rbp),%rdx
add    $0x20,%rdx
lea    0xe5e(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x30(%rbp),%rsi
add    $0x20,%rsi
lea    -0x30(%rbp),%rdx
add    $0x20,%rdx
lea    0xe40(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x20(%rbp),%esi
mov    -0x20(%rbp),%edx
lea    0xe2c(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x38,%rsp
movaps 0xefe(%rip),%xmm0
movaps %xmm0,0x20(%rsp)
movaps 0xee2(%rip),%xmm0
movaps %xmm0,0x10(%rsp)
movaps 0xec6(%rip),%xmm0
movaps %xmm0,(%rsp)
lea    0x20(%rsp),%r14
lea    0x10(%rsp),%r15
lea    0xee1(%rip),%r12
mov    %rsp,%rbx
mov    %r12,%rdi
mov    %rbx,%rsi
mov    %rbx,%rdx
xor    %eax,%eax
call   1030 <printf@plt>
mov    %r12,%rdi
mov    %rbx,%rsi
mov    %rbx,%rdx
xor    %eax,%eax
call   1030 <printf@plt>
mov    %r12,%rdi
mov    %rbx,%rsi
mov    %rbx,%rdx
xor    %eax,%eax
call   1030 <printf@plt>
mov    %r12,%rdi
mov    %r15,%rsi
mov    %r15,%rdx
xor    %eax,%eax
call   1030 <printf@plt>
mov    %r12,%rdi
mov    %r15,%rsi
mov    %r15,%rdx
xor    %eax,%eax
call   1030 <printf@plt>
mov    %r12,%rdi
mov    %r14,%rsi
mov    %r14,%rdx
xor    %eax,%eax
call   1030 <printf@plt>
mov    %r12,%rdi
mov    %r14,%rsi
mov    %r14,%rdx
xor    %eax,%eax
call   1030 <printf@plt>
mov    0x10(%rsp),%edx
mov    %r12,%rdi
mov    %edx,%esi
xor    %eax,%eax
call   1030 <printf@plt>
add    $0x38,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
@__const.main.a = [3 x [4 x i32]] [[4 x i32] [i32 1, i32 3, i32 5, i32 7], [4 x i32] [i32 9, i32 11, i32 13, i32 15], [4 x i32] [i32 17, i32 19, i32 21, i32 23]]
@.str = [7 x i8] c"%d,%d\0A\00"
define void @main() {
%1 = alloca [3 x [4 x i32]]
%2 = bitcast [3 x [4 x i32]]* %1 to i8*
%3 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%4 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%5 = getelementptr inbounds [4 x i32], [4 x i32]* %4, i64 0, i64 0
%6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), [4 x i32]* %3, i32* %5)
%7 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%8 = getelementptr inbounds [4 x i32], [4 x i32]* %7, i64 0, i64 0
%9 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%10 = getelementptr inbounds [4 x i32], [4 x i32]* %9, i64 0
%11 = getelementptr inbounds [4 x i32], [4 x i32]* %10, i64 0, i64 0
%12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32* %8, i32* %11)
%13 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%14 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%15 = getelementptr inbounds [4 x i32], [4 x i32]* %14, i64 0, i64 0
%16 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), [4 x i32]* %13, i32* %15)
%17 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 1
%18 = getelementptr inbounds [4 x i32], [4 x i32]* %17, i64 0, i64 0
%19 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%20 = getelementptr inbounds [4 x i32], [4 x i32]* %19, i64 1
%21 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32* %18, [4 x i32]* %20)
%22 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 1
%23 = getelementptr inbounds [4 x i32], [4 x i32]* %22, i64 0, i64 0
%24 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%25 = getelementptr inbounds [4 x i32], [4 x i32]* %24, i64 1
%26 = getelementptr inbounds [4 x i32], [4 x i32]* %25, i64 0, i64 0
%27 = getelementptr inbounds i32, i32* %26, i64 0
%28 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32* %23, i32* %27)
%29 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 2
%30 = getelementptr inbounds [4 x i32], [4 x i32]* %29, i64 0, i64 0
%31 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%32 = getelementptr inbounds [4 x i32], [4 x i32]* %31, i64 2
%33 = getelementptr inbounds [4 x i32], [4 x i32]* %32, i64 0, i64 0
%34 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32* %30, i32* %33)
%35 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 2
%36 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%37 = getelementptr inbounds [4 x i32], [4 x i32]* %36, i64 2
%38 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), [4 x i32]* %35, [4 x i32]* %37)
%39 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 1
%40 = getelementptr inbounds [4 x i32], [4 x i32]* %39, i64 0, i64 0
%41 = load i32, i32* %40
%42 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%43 = getelementptr inbounds [4 x i32], [4 x i32]* %42, i64 1
%44 = getelementptr inbounds [4 x i32], [4 x i32]* %43, i64 0, i64 0
%45 = getelementptr inbounds i32, i32* %44, i64 0
%46 = load i32, i32* %45
%47 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32 %41, i32 %46)
ret void
}

LLVM IR (-O2):
@__const.main.a = [3 x [4 x i32]] [[4 x i32] [i32 1, i32 3, i32 5, i32 7], [4 x i32] [i32 9, i32 11, i32 13, i32 15], [4 x i32] [i32 17, i32 19, i32 21, i32 23]]
@.str = [7 x i8] c"%d,%d\0A\00"
define void @main() {
%1 = alloca [3 x [4 x i32]]
%2 = bitcast [3 x [4 x i32]]* %1 to i8*
%3 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0
%4 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 0, i64 0
%5 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), [4 x i32]* %3, i32* %4)
%6 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32* %4, i32* %4)
%7 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), [4 x i32]* %3, i32* %4)
%8 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 1, i64 0
%9 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 1
%10 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32* %8, [4 x i32]* %9)
%11 = getelementptr inbounds [4 x i32], [4 x i32]* %9, i64 0, i64 0
%12 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32* %8, i32* %11)
%13 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i64 0, i64 2
%14 = getelementptr inbounds [4 x i32], [4 x i32]* %13, i64 0, i64 0
%15 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32* %14, i32* %14)
%16 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), [4 x i32]* %13, [4 x i32]* %13)
%17 = load i32, i32* %8
%18 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32 %17, i32 %17)
ret void
}