What are convincing examples where pointer arithmetic is preferable to array subscripting?

余生长醉 提交于 2019-11-30 09:04:46

Getting a pointer again instead of a value:

One usually uses pointer arithmetic when they want to get a pointer again. To get a pointer while using an array index: you are 1) calculating the pointer offset, then 2) getting the value at that memory location, then 3) you have to use & to get the address again. That's more typing and less clean syntax.

Example 1: Let's say you need a pointer to the 512th byte in a buffer

char buffer[1024]
char *p = buffer + 512;

Is cleaner than:

char buffer[1024];
char *p = &buffer[512];

Example 2: More efficient strcat

char buffer[1024];
strcpy(buffer, "hello ");
strcpy(buffer + 6, "world!");

This is cleaner than:

char buffer[1024];
strcpy(buffer, "hello ");
strcpy(&buffer[6], "world!");

Using pointer arithmetic ++ as an iterator:

Incrementing pointers with ++, and decrementing with -- is useful when iterating over each element in an array of elements. It is cleaner than using a separate variable used to keep track of the offset.


Pointer subtraction:

You can use pointer subtraction with pointer arithmetic. This can be useful in some cases to get the element before the one you are pointing to. It can be done with array subscripts too, but it looks really bad and confusing. Especially to a python programmer where a negative subscript is given to index something from the end of the list.

char *my_strcpy(const char *s, char *t) {
  char *u = t;
  while (*t++ = *s++);
  return u;
}

Why would you want to spoil such a beauty with an index? (See K&R, and how they build on up to this style.)There is a reason I used the above signature the way it is. Stop editing without asking for a clarification first. For those who think they know, look up the present signature -- you missed a few restrict qualifications.

Structure alignment testing and the offsetof macro implementation.

Pointer arithmetic may look fancy and "hackerish", but I have never encountered a case it was FASTER than the standard indexing. Just the opposite, I often encountered cases when it slowed the code down by a large factor.

For example, typical sequential looping through an array with a pointer may be less efficient than looping with a classic index on a modern processors, that support SSE extensions. Pointer arithmetic in a loop sufficiently blocks compilers from performing loop vectorization, which can yield typical 2x-4x performance boost. Additionally, using pointers instead of simple integer variables may result in needless memory store operations due to pointer aliasing.

So, generally pointer arithmetic instead of standard indexed access should NEVER be recommended.

iterating through a 2-dimensional array where the position of a datum does not really matter
if you dont use pointers, you would have to keep track of two subscripts
with pointers, you could point to the top of your array, and with a single loop, zip through the whole thing

If you were using an old compiler, or some kind of specialist embedded systems compiler, there might be slight performance differences, but most modern compilers would probably optimize these (tiny) differences out.

The following article might be something you could draw on - depends on the level of your students:

http://geeks.netindonesia.net/blogs/risman/archive/2007/06/25/Pointer-Arithmetic-and-Array-Indexing.aspx

You're asking about C specifically, but C++ builds upon this as well:

Most pointer arithmetic naturally generalizes to the Forward Iterator concept. Walking through memory with *p++ can be used for any sequenced container (linked list, skip list, vector, binary tree, B tree, etc), thanks to operator overloading.

Something fun I hope you never have to deal with: pointers can alias, whereas arrays cannot. Aliasing can cause all sorts of non-ideal code generation, the most common of which is using a pointer as an out parameter to another function. Basically, the compiler cannot assume that the pointer used by the function doesn't alias itself or anything else in that stack frame, so it has to reload the value from the pointer every time it's used. Or rather, to be safe it does.

Often the choice is just one of style - one looks or feels more natural than the other for a particular case.

There is also the argument that using indexes can cause the compiler to have to repeatedly recalculate offsets inside a loop - I'm not sure how often this is the case (other than in non-optimized builds), but I imagine it happens, but it's probably rarely a problem.

One area that I think is important in the long run (which might not apply to an introductory C class - but learn 'em early, I say) is that using pointer arithmetic applies to the idioms used in the C++ STL. If you get them to understand pointer arithmetic and use it, then when they move on to the STL, they'll have a leg up on how to properly use iterators.

#include ctype.h
void skip_spaces( const char **ppsz )
{
  const char *psz = *ppsz;
  while( isspace(*psz) )
    psz++;
  *ppsz = psz;
}

void fn(void)
{
  char a[]="  Hello World!";
  const char *psz = a;
  skip_spaces( &psz );
  printf("\n%s", psz);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!