C-指针和下标问题

C-指针和下标问题

归属感 发布于 2017-09-24 字数 165 浏览 1241 回复 3

两段用于数组初始化代码:
1.用数组下标初始化

int a[10]
int k;
for(k=0;k<10;k++)
a[k] = 0;

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

想挽留 2017-10-20 3 楼

直觉上可能会觉得第二个因为没有乘法要更快,其实这是错的。现代的编译器编译这两段代码会得到完全相同的汇编指令,大致有这几种情况:

 int *p = &a[N];
for(--p; p != a; --p)
{
*p = 0;
}

如果循环的逻辑不允许倒序执行,

 for(int *p = a; p < (a+N); ++p)
{
...
}

N是变量的情况下第一种可以省一个临时寄存器(存a+N),否则是一样的
如果循环中用到了k,那么

 k = N;
for(--k;k!=0;--k)
{
a[k]...
}

这个在比较新的x86 CPU上其实也是一样快的,因为x86上有专用的指令用来计算4 * k + a这样的结构(4也可以是1,2,3等),而k!=0因为可以利用--k的flag寄存器,不需要额外计算(p - a)这样的值,又少了一个周期,所以总的来说是一样快的。
如果不允许倒序:

 for(int k = 0; k < N; ++k)
{
a[k]...
}

每个循环慢一个指令周期。

总之就是现代的编译器完全可以替你处理这些鸡毛蒜皮的小问题,所以你可以不用考虑这些,直接用你最习惯的就行了。你以为比较快的写法,可能反而因为不常见,得不到编译器充分的优化,结果变慢了。

偏爱自由 2017-10-13 2 楼

数组下表访问有乘法运算,而指针访问是没有的
展开一下就明白了
代码1展开:

 a[k] = *(a + k ) = *( (int * )a + k * sizeof(int)).

代码2展开:

 p++ = *(p + 1 ) = *( (int * )p + sizeof(int)).

所以这里就明白了,加减运算要比乘除法运算快很多,所以造成代码2比代码1快

归属感 2017-10-05 1 楼

2中方法的效率都极差,因为

1) 初始化整数数组的时候,分配内存的时候会自动置0,初始化的时候没必要

2) 如果在后面的逻辑需要再次全部置0, 用循环是很糟糕的方法。正确的方法是用memset(a,0, sizeof(int)*10);

3) 产品中没人会写出这样的代码,我找了个简单的开源项目grep了一下, 用memset清空数组被使用了1697次。

thu@geekdev:~$ ffc memset | wc -l
1697