C – 何时使用指针算法,何时使用数组索引?

在C中,何时优先使用一个而不是另一个?

这通常取决于具体情况。 我认为没有经验法则。

在某些情况下,数组索引更好。 例如,当您分配了一个数组

char* ptr = malloc(SIZE); 

并且您需要ptr的值不要更改,因为您想稍后释放它,然后您可以使用索引。

或者,如果您将指针作为函数参数

 void func(char* ptr) 

并且你需要遍历数组,然后你可以增加指针本身,你不需要创建一个新的变量用作索引。

但在大多数情况下,这取决于您自己的偏好。

这实际上是风格和编码约定的问题,因为在C p[i]定义为与*(p+i)相同,其中p是指针而i是整数索引。 AFAIK你甚至可以写i[p]但那很难看。

在C ++中并不总是如此(这使您能够定义operator []等…)。

在这种情况下,我个人不喜欢手工编码&p[i]并且更喜欢p+i

“数组索引”只是包含“指针算术”的语法糖。 它纯粹是化妆品,只是另一种符号,意味着使用一种或另一种是个人偏好的问题。

通常隐藏在你所问的内容的真正问题是何时使用随机访问以及何时使用顺序访问(使用“指针算术”意味着指针的顺序递增/递减不超过1)。 答案是:尽可能使用顺序访问,只在必要时才使用随机访问。

只要性能不受影响,依靠最小的需求集来实现算法总是更好的主意。 随机访问比顺序访问更强烈,这意味着在合理可能的情况下应该避免使用前者。

在性能方面,最好使用指针算法(至少禁用编译器优化),因为在迭代数组时,您不必增加单独的变量。 另见K&R第97页(第二版)。

否则它只是一个编码风格的问题。

在编译时不知道数据结构的大小时,指针很有用。 例如,当你不知道字符串的长度是多少,或者你想要多少整数时,等等。 在这种情况下,指针可以根据需要动态分配内存。

另一方面,arrays降低了灵活性。

除此之外还有更多的东西。

根据MISRA C ++ 2008(规则5-0-15):数组索引应该是指针算术的唯一forms。

但是这个规则有一个例外:

递增/递减运算符可用于通过指向数组的指针实现的迭代器

 template < typename IterType > uint8_t sum_values ( IterType iter, IterType end ) { uint8_t result = 0; while ( iter != end ) { result += *iter; ++iter; // Compliant by exception } return result; } void my_fn ( uint8_t * p1, uint8_t p2[ ] ) { uint8_t index = 0; uint8_t * p3; uint8_t * p4; *p1 = 0; ++index; index = index + 5; p1 = p1 + 5; // Non-compliant – pointer increment p1[ 5 ] = 0; // Non-compliant – p1 was not declared as array p3 = &p1[ 5 ]; // Non-compliant – p1 was not declared as array p2[ 0 ] = 0; p2[ index ] = 0; // Compliant p4 = &p2[ 5 ]; // Compliant } uint8_t a1[ 16 ]; uint8_t a2[ 16 ]; my_fn ( a1, a2 ); my_fn ( &a1[ 4 ], &a2[ 4 ] ); uint8_t a[ 10 ]; uint8_t * p; p = a; *( p + 5 ) = 0; // Non-compliant p[ 5 ] = 0; // Compliant sum_values ( &a1[ 0 ], &a1[ 16 ] );