1

The following is the C code:

char *ptr[100];
printf("%s\n",*ptr++);

My question is: we know that array name is not a variable (Ritchie's book "The C programming language" Page 99), so if we define

int *pa,a[5];

This is legal:

pa = a; pa++;

while this is illegal:

a++;

Here char *ptr[100] defines a char pointer array, so ptr represents the initial address of the array. For the above code, if *ptr++ means *(ptr++), this is illegal because array name cannot be used as a variable, and also it's meaningless because *(ptr++) still gets an address as opposed to %s. However, if *ptr++ means (*ptr)++, it also looks strange... Can anyone help to understand this?

The above is my thinking process, my question is: how can *ptr++ give us a string as the code printf("%s\n",*ptr++); says?

Thomas D.
  • 87
  • 8
  • 2
    Your question is unclear. I don't feel I understand it. – machine_1 Mar 21 '18 at 16:14
  • What do you mean by saying *array name cannot be used as a variable*? `ptr` is a variable and it's also an array's name – SHG Mar 21 '18 at 16:14
  • I mean if `int *pa, a[5];` you cannot use expressions like `a=pa;` or `a++;` – Thomas D. Mar 21 '18 at 16:19
  • See Ritchie's book 'C programming language' Page 99 – Thomas D. Mar 21 '18 at 16:20
  • Possible duplicate of [C/C++ int\[\] vs int\* (pointers vs. array notation). What is the difference?](https://stackoverflow.com/questions/11555997/c-c-int-vs-int-pointers-vs-array-notation-what-is-the-difference) – sg7 Mar 21 '18 at 16:22
  • It's pretty much the same reason why `pa = ...` is allowed while `a = ` is not allowed: An array is never an assignable entity, but a pointer is. – cmaster - reinstate monica Mar 21 '18 at 16:27
  • Did you try to compile this code? If so, did the compiler complain about it? If so, what was the error message? – John Bode Mar 21 '18 at 16:32
  • @John Bode I'm trying to understand the mechanism. It's easy to compile successfully because this example is from a textbook... – Thomas D. Mar 21 '18 at 16:51
  • @Thomas - that's the point, `*ptr++` is a *constraint violation* (`ptr` is not a modifiable lvalue, and thus may not be the operand of the the `++` operator), and the compiler must *at least* issue a diagnostic for it (on the order of "invalid lvalue in increment"). Even *good* textbooks contain errors in code samples. – John Bode Mar 21 '18 at 18:01

4 Answers4

1

Postfix increment ++ has a higher precedence than dereference *.

Thus, *ptr++ is interpreted as *(ptr++). And as you've correctly figured out, ptr++ isn't allowed if ptr is an array (of anything, values or pointers).

If ptr is a pointer, then *ptr++ will indeed increment the pointer (so it will point to the next value after the operation), and this expression will return the current pointed-to value (before increment of the pointer). This expression is indeed sometimes used, e.g. for copying memory areas, e.g.:

while (...) {
    *dest++ = *src++; // Copy the current element, then increment both pointers
}

*ptr++ doesn't necessarily give you a string — it gives you a string if and only if ptr is pointing to a string. And in this case, it's not necessary to post-increment just to get the string — *ptr would be enough. ++ is done for another purpose.

For example, it ptr is a pointer to an "array" of strings (i.e. a pointer to a pointer to achar, i.e. char **ptr), then you could print all the strings like this:

int i;
for (i = 0; i < N; ++i) {
    printf("%s\n",*ptr++); // '++' "jumps" to the next string
}
Alex Shesterov
  • 26,085
  • 12
  • 82
  • 103
  • Thank you for your reply. My understanding is `ptr` is a pointer-to-pointer which points to the address of `ptr[0]`, so `*ptr == ptr[0]`, `*ptr+1 == ptr[1]` etc. So if we want to get the string, it seems that we need to dereference again? – Thomas D. Mar 21 '18 at 16:31
  • You are right about `*ptr == ptr[0]` and `*(ptr+1) == ptr[1]` (note the grouping). But in C, a "string" is _a null-terminated "array" of characters_. So if you dereference a string, you'll actually get the first character. Having `char** ptr` - this could be an array of strings; then `*ptr` or `ptr[0]` is the first string, `*(ptr+1)` or `ptr[1]` is the second string, and so on; `**ptr` or `ptr[0][0]` is the first character of the first string, `*(*(ptr + 1) + 2)` or `ptr[1][2]` is the third character of the second string, etc. – Alex Shesterov Mar 21 '18 at 16:41
0

I believe this link should help you.

C/C++ int[] vs int* (pointers vs. array notation). What is the difference?

The array notation has a bounds limit while the pointer notation does not.

If you wanted to access the next in the array with array notation it would look something like a[n++] n being whatever the current index of the array you are at. Where as assigning ptr to a sets ptr to the first index of the array and you can increment a pointer.

Vilyanare
  • 44
  • 2
0

*ptr++ is parsed as *(ptr++) - apply the ++ operator to ptr, then dereference the result.

As written, this results in a constraint violation - ptr is an array of pointers to char, and an expression of array type is a non-modifiable lvalue, and as such may not be the target of an assignment or the operand of the ++ and -- operators.

The line

printf("%s\n",*ptr++);

should (indeed, must) result in the compiler issuing a diagnostic on the order of "invalid lvalue in increment" or something along those lines.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Yes, you're right, there is `error: lvalue required as increment operand` when I use `*ptr++`. I listed all the possible solutions below. If you have time, could you please look at it for me. Thanks – Thomas D. Mar 21 '18 at 20:42
0

No. 1:

void main(void)
{
    int i;
    char *ptr[3]={"how","are","you"};
    for (i=0;i<3;i++)
        printf("%s\n",ptr[i]);
}

This prints out correct answer. Good!

No.2:

void main(void)
{
    int i;
    char *ptr[3];
    *ptr[0] = "how";
    *ptr[1] = "are";
    *ptr[2] = "you";
    for (i=0;i<3;i++)
        printf("%s\n",ptr[i]);
}

warning: assignment makes integer from pointer without a cast [enabled by default].....Why can't initialize like this?

No.3:

void main(void)
{
    int i;
    char *ptr[3]={"how","are","you"};
    printf("%s\n",*ptr++);
}

error: lvalue required as increment operand....Why can't we use *ptr++?

Thomas D.
  • 87
  • 8