使指针数组中的所有指针指向C中的相同内容?

时间:2015-03-05 16:12:26

标签: c performance pointers memory

我有这两个定义:

uint8_t *idx[0x100];
uint8_t  raw[0x1000];

除了循环idx的每个元素以将它们全部指向raw[0]之外,还有其他方法吗?

for (i=0; i<sizeof(raw); i++)
    idx[i] = &raw[0];

必须有比↑更快的方式。是否有等价于memset的指针?

3 个答案:

答案 0 :(得分:4)

简单,直接的循环可能是最好的方法(注意当前循环中有一个错误,正如其他人所指出的那样)。

优点是这些循环非常容易优化,这是一个常见的情况,编译器已经非常擅长它,并且您的编译器将根据需要使用向量指令和其他优化来保持它非常快,而不需要手动优化自己。 当然,与手工优化相比,它更具可读性,更易于维护。

当然,如果有一个特殊情况,例如,如果你想用空指针填充它,或者如果你知道编译时内容是什么,那么有一些更有效的方法来做到这一点,但是一般情况下,编译器可以轻松优化代码,这是获得良好性能的最简单方法。

答案 1 :(得分:1)

我们只看到一段代码,如果要初始化指向全局数组uint8_t的全局指针数组,则有一种更快的方法:编写显式初始化程序。初始化在编译时完成,在执行时几乎没有时间。

如果阵列是自动的,我担心没有更快的方法可以做到这一点。如果您的编译器很聪明并且指示使用优化(-O2,-O3等),它可能会展开循环并生成非常高效的代码。查看程序集输出以验证这一点。如果没有,您可以自己展开循环:

假设数组大小是4的倍数:

for (i = 0; i < sizeof(idx) / sizeof(*idx); i += 4)
    idx[i] = idx[i+1] = idx[i+2] = idx[i+3] = &raw[0];

请注意,你应该小心使用sizeof运算符:除了使用错误的数组进行大小计算之外,你的代码还有两个隐含的假设:

  • 数组元素是char
  • idx是一个数组,而不是指向数组的指针。

建议使用sizeof(idx) / sizeof(*idx)来计算数组元素的数量:此表达式适用于所有数组元素类型,但idx仍然需要是数组类型。定义一个宏:

#define countof(a)  (sizeof(a) / sizeof(*(a)))

使它更方便,但如果a是指针,则隐藏问题。

答案 2 :(得分:1)

从性能工程的角度来看,确实有一种方法可以使它比

更快
for (i=0; i<sizeof(raw); i++)
    idx[i] = &raw[0];

如果在关闭编译器中的优化器后进行比较。但差别可能很小。

让我们这样做:

uint8_t *idx[0x100];
uint8_t  raw[0x1000];

#define lengthof(arr)    (sizeof(arr) / sizeof(*arr))

uint8_t *start = idx;
int length = lengthof(idx);
uint8_t *end = idx + (length & ~1);
for (; start < end;)
{
    *start++ = raw;
    *start++ = raw;
}
if (length & 1)
    *start++ = raw;

这主要是因为两个原因:

  1. 直接操作指针。如果你idx[i],在汇编时,每次都会执行(idx + i * sizeof *idx),而*start已经有了答案。
  2. 每次迭代中的重复操作。这样,代码在保持局部性的同时将具有较少的分支。 gcc -O2很可能会为你做到这一点。