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?

9
  • 2
    Your question is unclear. I don't feel I understand it. Commented Mar 21, 2018 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 Commented Mar 21, 2018 at 16:14
  • I mean if int *pa, a[5]; you cannot use expressions like a=pa; or a++; Commented Mar 21, 2018 at 16:19
  • See Ritchie's book 'C programming language' Page 99 Commented Mar 21, 2018 at 16:20
  • Possible duplicate of C/C++ int[] vs int* (pointers vs. array notation). What is the difference? Commented Mar 21, 2018 at 16:22

4 Answers 4

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
}
Sign up to request clarification or add additional context in comments.

2 Comments

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?
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.
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.

Comments

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.

1 Comment

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
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++?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.