简体   繁体   中英

Iterating a pointer vs character array

I am trying to understand a bit more about incrementing arrays vs pointers. For example, the following works:

char string[] = "Hi";
char * pstring = string;
while(*pstring)
    printf("%c", *pstring++);

But if I remove the pointer, it will not:

char string[] = "Hi";
while(*string)
    printf("%c", *string++);

Why does the first one work? What's the main difference between iteration through a pointer and array?

There's really quite a lot of rationales for why the second one doesn't work. I'm sure you know this, but I'll just reiterate: an array is not a pointer. Arrays are only converted to pointers. This is automatic, and it happens "very often", but arrays and pointers are still different types. In terms of the language, you simply cannot assign to an array (lvalues of array type are not "modifiable lvalues"), and, specifically, the "hidden" string = string + 1 assignment in string++ does not work. You can, of course, assign to a pointer variable. For this reason, in the C standard, ++ is defined to work only on numeric ("real") and pointer types, and this means you aren't allowed to give it an array.

In terms of why the rules are like this, one train of thought starts by noticing that an array type is only "complete" when it has a size—ie if you have a variable of array type, its size is a part of its type. Trying to mutate string with arithmetic, as you do here, would require changing the type of string , because the size would change, but this is not allowed in C. (Note that char string[]; is an invalid declaration because it doesn't specify a size; when you added the initializer you told C to infer the size ( 3 ) from it.) In the pointer version, pstring is a char* , and so is pstring + 1 , so there's no issue. In the array version, you'd need to have char string[3] before the loop and char string[1] afterwards. Worse, the final size of string would depend on the data in it, so there'd be no way to predict it from the language's point of view. Best not open that can of worms, no?

The idea of incrementing string also breaks down because, in C, an "array object" is more than "a bunch of contiguous elements". When you declare string , yes, you create a bunch of char objects that are contiguous in memory, but you also "bless" (this is not a technical term, unless you're using Perl:)) that memory into being a char[3] object. Probably, in terms of the actual machine, this "blessing" doesn't actually do or mean anything, but, in terms of the abstract machine that C programs run on, there is a difference. Specifically, there is neither an char[2] object located at memory address string + 1 nor an char[1] at string + 2 . Thus, were you to increment string , there would be no array for string to refer to anymore.

I suppose you can boil all this down to the intuition that an array is really just "a bunch of variables". That is, when you declared char string[3]; , that should feel like you did char string_0, string_1, string_2; . This is just like if you had struct { int x; char y; } test; struct { int x; char y; } test; —this feels like writing int test_x; char test_y; int test_x; char test_y; . "Incrementing a group of variables" is quite meaningless, so of course string++ and test++ are disallowed. With string , you have the option to create a char *pstring , such that pstring = &string_0 , pstring + 1 = &string_1 , pstring + 2 = &string_2 , but that doesn't change the fact that doing arithmetic on string itself (especially destructively incrementing it) doesn't make sense.

Here's my two bits....

Why does the first one work?

The pointer "pstring" is a 'variable'. This means that the pointer "pstring" can be re-assigned a new value.

pstring++ is "pstring = pstring + 1" (allowed).

Other valid pointer operations are:

  • Assignment of pointers of the same type.
  • Adding or Subtracting a pointer and an integer.
  • Subtracting or Comparing two pointers to members of the same array.
  • Assigning or Comparing a pointer to zero(NULL).

What's the main difference between iteration through a pointer and array?

The name of the array(synonymous with the location of the first element) is not a "variable" and will always refer to the same storage. Though an integer can be added to or subtracted from an array name, re-assigning a new value to an array name is illegal.

string++ is "string = string + 1" (not allowed).

The difference in coding is extrapolated further in the following:

char string[] = "Hi";
int i = 0;
while(*(string+i)){ // or string[i]
  printf("%c", *(string+i));// or string[i]
  i++;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM