数组的下标访问和指针访问方式效率分析比较
2015-07-22 11:36
375 查看
1、
int array[10], a;
for (a = 0; a < 10; a ++)
{
array[a] = 0;
}
该组使用下标方式赋值,为了对下标表达式求值,编译器在程序中插入指令,取的a的值,并把它与整型的长度(也就是4)相乘,这个乘法需要花费一定的时间和空间
2、
int array[10], *ap;
for (ap = array; ap <array + 10; ap ++)
{
*ap = 0;
}
该组使用指针方式赋值,尽管这里并不存在下标,但还是存在乘法运算,现在这个乘法运算出现在for语句的调整部分,1这个值必须与整型长度相乘,然后再与指针相加,但这里存在一个重大区别:循环每次执行时,执行乘法运算的部分都是两个相同的数(1和4).结果,这个乘法只在编译时执行一次——程序现在包含了一条指令,把4与指针相加,程序在运行时并不执行乘法运算。
摘自《c和指针》8.1.3 指针与下标
书上讲指针法要比下标法访问数组速度快,是嘛?
我觉得楼主的问题需要更具体一些,我们区分如下三种情况:
1、定义了数组 a
, 通过 a[i] 和 *(a+i) 来访问
2、一个指针 p 指向一段合法空间,通过 p[i] 和 *(p+i) 来访问
3、定义了数组 a
,令指针 p = a,分别通过 p 和 a 来访问
对于情况 1、2, 访问方式 [] 和 * 是完全等价的,没有差别。我强调一下,对于数组 a, a[i] 与 *(a+i) 是完全一样的。类似地,对于指针 p, *(p+i) 与 p[i] 也是完全一样的。一样指的是生成的汇编代码没有差别。
真正有差别的是 3, 差别在于通过 a 访问还是通过 p 访问,而不在于用 [] 还是用 *
对于 3, 假如要访问 a[i]
(I) 通过 a 访问
系统只需要计算常量 a 与 i*sizeof(type) 之和,然后访问该地址
(II) 通过 p 访问
p 是个变量,系统必须先访问 p 的地址,得到 p 的值,然后计算该值 v(p) 与 i*sizeof(type) 之和, 然后再访问得到的地址。
相比之下,(II) 要稍微慢一些(指针慢)。
通过指针访问唯一有可能快的地方是使用 ++ 进行移动,然后通过 *p 访问。
但只适用与以下情况:
(a) 硬件对自增有支持,否则 ++ 被转换为 +sizeof(type) 的加法指令,也快不了。
(b) 依次遍历数组
总之,我得出如下结论,在绝大多数情况下,指针与数组相比,没有效率上的优势,有时反而更慢。指针的真正优势是灵活,好用。
ps>; 对于优化的一些补充。
的确,通过 [] 和 * 都可访问任何地址(包括 coredump 的情况),但正如我前面所说的,差别不再在 [] 还是用 * ,在于通过指针访问还是通过数组访问。
对于 int a[10], 你可以用 a[100] 或 a[-10] 访问数组以外的空间,但后果是未定义的。编译器可以无视这种代码,假设通过 a 只会访问 a..a+9,并将之作为优化依据。
对于 int *p ,p 可以指向任何 int 数据。
int array[10], a;
for (a = 0; a < 10; a ++)
{
array[a] = 0;
}
该组使用下标方式赋值,为了对下标表达式求值,编译器在程序中插入指令,取的a的值,并把它与整型的长度(也就是4)相乘,这个乘法需要花费一定的时间和空间
2、
int array[10], *ap;
for (ap = array; ap <array + 10; ap ++)
{
*ap = 0;
}
该组使用指针方式赋值,尽管这里并不存在下标,但还是存在乘法运算,现在这个乘法运算出现在for语句的调整部分,1这个值必须与整型长度相乘,然后再与指针相加,但这里存在一个重大区别:循环每次执行时,执行乘法运算的部分都是两个相同的数(1和4).结果,这个乘法只在编译时执行一次——程序现在包含了一条指令,把4与指针相加,程序在运行时并不执行乘法运算。
摘自《c和指针》8.1.3 指针与下标
书上讲指针法要比下标法访问数组速度快,是嘛?
我觉得楼主的问题需要更具体一些,我们区分如下三种情况:
1、定义了数组 a
, 通过 a[i] 和 *(a+i) 来访问
2、一个指针 p 指向一段合法空间,通过 p[i] 和 *(p+i) 来访问
3、定义了数组 a
,令指针 p = a,分别通过 p 和 a 来访问
对于情况 1、2, 访问方式 [] 和 * 是完全等价的,没有差别。我强调一下,对于数组 a, a[i] 与 *(a+i) 是完全一样的。类似地,对于指针 p, *(p+i) 与 p[i] 也是完全一样的。一样指的是生成的汇编代码没有差别。
真正有差别的是 3, 差别在于通过 a 访问还是通过 p 访问,而不在于用 [] 还是用 *
对于 3, 假如要访问 a[i]
(I) 通过 a 访问
系统只需要计算常量 a 与 i*sizeof(type) 之和,然后访问该地址
(II) 通过 p 访问
p 是个变量,系统必须先访问 p 的地址,得到 p 的值,然后计算该值 v(p) 与 i*sizeof(type) 之和, 然后再访问得到的地址。
相比之下,(II) 要稍微慢一些(指针慢)。
通过指针访问唯一有可能快的地方是使用 ++ 进行移动,然后通过 *p 访问。
但只适用与以下情况:
(a) 硬件对自增有支持,否则 ++ 被转换为 +sizeof(type) 的加法指令,也快不了。
(b) 依次遍历数组
总之,我得出如下结论,在绝大多数情况下,指针与数组相比,没有效率上的优势,有时反而更慢。指针的真正优势是灵活,好用。
ps>; 对于优化的一些补充。
的确,通过 [] 和 * 都可访问任何地址(包括 coredump 的情况),但正如我前面所说的,差别不再在 [] 还是用 * ,在于通过指针访问还是通过数组访问。
对于 int a[10], 你可以用 a[100] 或 a[-10] 访问数组以外的空间,但后果是未定义的。编译器可以无视这种代码,假设通过 a 只会访问 a..a+9,并将之作为优化依据。
对于 int *p ,p 可以指向任何 int 数据。
相关文章推荐
- 关于指针的一些事情
- Linux C函数参考手册(PDF版)
- ruby 数组使用教程
- Ruby中的数组和散列表的使用详解
- C#实现AddRange为数组添加多个元素的方法
- C#动态调整数组大小的方法
- Lua教程(十七):C API简介
- 详解Lua中的数组概念知识
- Perl中的列表和数组学习笔记
- 探索PowerShell (八) 数组、哈希表(附:复制粘贴技巧)
- C#中数组初始化与数组元素复制的方法
- C#交错数组用法实例
- PowerShell数组的一些操作技巧
- C#通过yield实现数组全排列的方法
- C#实现打造气泡屏幕保护效果
- C# Pointer指针应用实例简述
- Ruby简明教程之数组和Hash介绍
- C/C++数据对齐详细解析
- C语言查找数组里数字重复次数的方法