该二维数组在内存中用一维数组索引表示为:

    为了计算我们需要的元素地址,首先,第一个索引乘以4(矩阵宽度),然后加上第二个索引。这种被称为行优先,C/C++和Python常用这种方法。行优先的意思是:先写入第一行,接着是第二行,…,最后是最后一行。 另一种方法就是列优先,主要用在FORTRAN,MATLAB,R等。列优先的意思是:先写入第一列,然后是第二列,…,最后是最后一列。 多维数组与此类似。 我们看个例子:

    Listing 16.4: simple example

    1. int a[10][20][30];
    2. void insert(int x, int y, int z, int value)
    3. {
    4. a[x][y][z]=value;
    5. };

    Listing 16.5: MSVC 2010

    多维数组计算索引公式:address=6004x+304y+4z。因为int类型为32-bits(4字节),所以要乘以4。

    Listing 16.6: GCC 4.4.1

    1. public insert
    2. insert proc near
    3. x = dword ptr 8
    4. y = dword ptr 0Ch
    5. value = dword ptr 14h
    6. push ebp
    7. push ebx
    8. mov ebx, [ebp+x]
    9. mov eax, [ebp+y]
    10. mov ecx, [ebp+z]
    11. lea edx, [eax+eax] ; edx=y*2
    12. mov eax, edx ; eax=y*2
    13. shl eax, 4 ; eax=(y*2)<<4 = y*2*16 = y*32
    14. sub eax, edx ; eax=y*32 - y*2=y*30
    15. imul edx, ebx, 600 ; edx=x*600
    16. add eax, edx ; eax=eax+edx=y*30 + x*600
    17. lea edx, [eax+ecx] ; edx=y*30 + x*600 + z
    18. mov eax, [ebp+value]
    19. pop ebx
    20. retn
    21. insert endp

    Listing 16.7: Non-optimizing Xcode (LLVM) + thumb mode

    非优化的LLVM代码在栈中保存了所有变量,这是冗余的。元素地址的计算我们通过公式已经找到了。

    Listing 16.8: Optimizing Xcode (LLVM) + thumb mode

    1. _insert
    2. MOVW R9, #0x10FC
    3. MOV.W R12, #2400
    4. MOVT.W R9, #0
    5. RSB.W R1, R1, R1,LSL#4 ; R1 - y. R1=y<<4 - y = y*16 - y = y*15
    6. ADD R9, PC ; R9 = pointer to a array
    7. LDR.W R9, [R9]
    8. MLA.W R0, R0, R12, R9 ; R0 - x, R12 - 2400, R9 - pointer to a. R0=x*2400 + ptr to a
    9. ADD.W R0, R0, R1,LSL#3 ; R0 = R0+R1<<3 = R0+R1*8 = x*2400 + ptr to a + y*15*8 =
    10. ; ptr to a + y*30*4 + x*600*4
    11. STR.W R3, [R0,R2,LSL#2] ; R2 - z, R3 - value. address=R0+z*4 =

    很多函数参数的输入标志使用了位域。当然,可以使用bool类型来替代,只是有点浪费。