我们来看一下2组例子:
第一组例子:
下标表达式:
a = get_value();
array[a] = 0;
指针表达式:
a = get_value();
*(array + a) = 0;
第二组例子:
下标表达式:
int array[10], a;
for(a=0; a<10; a+=1) {
array[a] = 0;
}
指针表达式:
int array[10], *ap;
for(a=array; a < array + 10; ap++) {
*ap = 0;
}
这2组例子都是一个使用下标,一个使用指针,每组例子的2中方式都实现相同的效果,但这2组例子使用下标和指针访问数组元素效率是一样的吗?
第一组例子效率完全一致,第二组例子循环体所有区别,计数器1和整形长度相乘,然后和指针相加,每次执行乘法迅运算都是相同的1和4。而指针每次都是相同的1和4相乘,而且只是在编译时执行一次,后面就是把指针和4相加。
它们到底怎么工作的呢?接下来,我们就来研究一下:
一、先看一个下标版本
#include <stdio.h>
#define SIZE 50
int x[SIZE];
int y[SIZE];
int i;
int *p1, *p2;
void try1() {
for(i = 0; i < SIZE; i++) {
x[i] = y[i];
}
}
int main () {
try1();
return 0;
}
编译获得汇编代码:
.file "main.c"
.text
.globl x
.bss
.align 32
.type x, @object
.size x, 200
x:
.zero 200
.globl y
.align 32
.type y, @object
.size y, 200
y:
.zero 200
.globl i
.align 4
.type i, @object
.size i, 4
i:
.zero 4
.globl p1
.align 8
.type p1, @object
.size p1, 8
p1:
.zero 8
.globl p2
.align 8
.type p2, @object
.size p2, 8
p2:
.zero 8
.text
.globl try1
.type try1, @function
try1:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $0, i(%rip)
jmp .L2
.L3:
movl i(%rip), %eax
movl i(%rip), %ecx
cltq
movl y(,%rax,4), %edx
movslq %ecx, %rax
movl %edx, x(,%rax,4)
movl i(%rip), %eax
addl $1, %eax
movl %eax, i(%rip)
.L2:
movl i(%rip), %eax
cmpl $49, %eax
jle .L3
nop
nop
popq