Още по-забавни резултати 

t1.c:
GeSHi (C):
- #include <unistd.h> 
-   
- void main() 
- { 
- int a[2][2]; 
- int b; 
-   
- b = a[1][1]; 
- } 
-   
t2.c:
GeSHi (C):
- void main() 
- { 
- int *a; 
- int b; 
- b = *(a+4); 
- } 
-   
Асемблерен код на main() функцията, компилираме го без оптимизации:
t1:
0x08048384 <main+0>:    lea    0x4(%esp),%ecx
0x08048388 <main+4>:    and    $0xfffffff0,%esp
0x0804838b <main+7>:    pushl  0xfffffffc(%ecx)
0x0804838e <main+10>:   push   %ebp
0x0804838f <main+11>:   mov    %esp,%ebp
0x08048391 <main+13>:   push   %ecx
0x08048392 <main+14>:   sub    $0x20,%esp
0x08048395 <main+17>:   mov    0xfffffff4(%ebp),%eax
0x08048398 <main+20>:   mov    %eax,0xfffffff8(%ebp)
0x0804839b <main+23>:   add    $0x20,%esp
0x0804839e <main+26>:   pop    %ecx
0x0804839f <main+27>:   pop    %ebp
0x080483a0 <main+28>:   lea    0xfffffffc(%ecx),%esp
0x080483a3 <main+31>:   ret
t2:
0x08048384 <main+0>:    lea    0x4(%esp),%ecx
0x08048388 <main+4>:    and    $0xfffffff0,%esp
0x0804838b <main+7>:    pushl  0xfffffffc(%ecx)
0x0804838e <main+10>:   push   %ebp
0x0804838f <main+11>:   mov    %esp,%ebp
0x08048391 <main+13>:   push   %ecx
0x08048392 <main+14>:   sub    $0x10,%esp
0x08048395 <main+17>:   mov    0xfffffff4(%ebp),%eax
0x08048398 <main+20>:   add    $0x10,%eax
0x0804839b <main+23>:   mov    (%eax),%eax
0x0804839d <main+25>:   mov    %eax,0xfffffff8(%ebp)
0x080483a0 <main+28>:   add    $0x10,%esp
0x080483a3 <main+31>:   pop    %ecx
0x080483a4 <main+32>:   pop    %ebp
0x080483a5 <main+33>:   lea    0xfffffffc(%ecx),%esp
0x080483a8 <main+36>:   ret
Или демек 5 инструкции повече. Обаче компилираме ли го с флаг за оптимизация (O1 и нагоре), и двете генерират абсолютно идентичен код:
0x08048384 <main+0>:    lea    0x4(%esp),%ecx
0x08048388 <main+4>:    and    $0xfffffff0,%esp
0x0804838b <main+7>:    pushl  0xfffffffc(%ecx)
0x0804838e <main+10>:   push   %ebp
0x0804838f <main+11>:   mov    %esp,%ebp
0x08048391 <main+13>:   push   %ecx
0x08048392 <main+14>:   pop    %ecx
0x08048393 <main+15>:   pop    %ebp
0x08048394 <main+16>:   lea    0xfffffffc(%ecx),%esp
0x08048397 <main+19>:   ret
Има една разлика между масивите и указателите обаче - масивите могат да бъдат в стека или data секцията (в зависимост от това дали са локални/глобални променливи), указателите се очаква да сочат към памет в хийпа. Обаче последното не е задължително - примерно ако се ползва alloca() няма да е така.
Обаче и при това положение, не виждам разлика. Паметта би трябвало да се dereference-ва еднакво бързо без значение къде е. Performance драми може да има с TLB misses при големи матрици, но това трябва да е валидно и за двата варианта. Другото което си мисля е дали линукс ядрото не предпочита при нужда да pageout-ва страници памет от хийпа пред страници памет от стека, ама много ме съмнява да (може да) го прави, а и не виждам с какво това би било по-умно от LRU стратегията.  
Та все още не мога да се сетя защо едното трябва да е по-бързо от другото.
В хийпа трябва да е по-бавно заради malloc() ама ако е малка матрицата може да го заделим в стека и тва е доста бърза операция (измества се само стек пойнтера). После, не е казано че трябва да ползваме malloc() въобще, може и сaмо с mmap(), което ще е малко по-бързо.
Ако изключим времето за заделяне и освобождаваме, двете трябва да са еднакво бързи.