1. 数组和指针操作对比
#include <stdio.h>
int main()
{
char *char_p, char_arr[5]={0,1,2};
short *short_p, short_arr[5]={1,2,3};
int *int_p, int_arr[5]={2,3,4};
char_p=char_arr;
short_p=short_arr;
int_p=int_arr;
printf("111\n");
(*(char_p+2)) ++;
printf("222\n");
char_arr[2] ++;
printf("111\n");
(*(short_p+2)) ++;
printf("222\n");
short_arr[2] ++;
printf("111\n");
(*(int_p+2)) ++;
printf("222\n");
int_arr[2] ++;
return 0;
}
横向对比:
这里可以很明显得出结论: 使用数组操作比指针高效!, 理由很简单, 编译器认为数组偏移多少成员其对于地址都是确定的, 取数组[0]和[3]没有区别就是个地址, 而指针偏移是一个独立行为,
所以要显性执行这个动作, 因此多出这部分指令!
这个表还有其他有意思的地方, 比如用int变量比char、short高效, char要and或者movzbl屏蔽溢出, short要lsl/lsr左移右移等
另外就是x86可以直接通过mov操作内存, 而ARM结构采用load-store, 必须先加载到寄存器, 进行操作后再回写内存
2. 指针作为函数参数(x86编译为例)
#include <stdio.h> void test1(int *p) { (*(p+4))++; } void test2(int *p) { p[4]++; } int main() { char *char_p, char_arr[5]={0,1,2}; short *short_p, short_arr[5]={1,2,3}; int *int_p, int_arr[5]={2,3,4}; char_p=char_arr; short_p=short_arr; int_p=int_arr; /* 省略上面测试代码*/ printf("333\n"); test1(int_p); test2(int_p); printf("444\n"); test1(int_arr); test2(int_arr); return 0; }
可以发现test1()、test2()反汇编实现是一样的, 不会因为“形式”上我用数组还是指针, 最终的本质是指针, 而调用无论传的是数组地址还是指针地址, 没有影响, 都是地址值而已
3. 数组作为函数参数(x86编译为例)
代码和上面一样就不贴了, 只是将参数改成数组 /* void test1(int *p) { (*(p+4))++; } void test2(int *p) { p[4]++; } */ void test1(int p[]) { (*(p+4))++; } void test2(int p[]) { p[4]++; }
反汇编的结果发现和上面函数形参是指针的一模一样! 也就是说虽然我的参数看起来像数组, 但实际上由于没有指定成员数量实际分配内存, 所以编译器还是把参数当做指针对待!
结论:
a. “真实”数组操作比指针高效
b. 有些看起来像数组, 实质是指针的, 指令走的还是指针那一套, 无论语法写的是*p++还是p[i]