0

I'm currently trying to learn C, with some prior experience in Python and pointer arithmetic is really confusing me right now.

#include <stdio.h>


int main()
{
    char *s[] = {"String1", "Literal2", "Pointers3"}; 
    printf("%c", s[1]+1);
    return 0;
}

Why does it print m instead of i ?

When I replace the format string with %s it does what I expect and prints out iteral2(Go to the 0th index of the 1st string literal then move 1 memory adress forward and print the rest).

How does this work, why does it print out a seemingly arbitrary character instead of the 1st(or 1th?) index when I use the %c format string.

2
  • You pass printf the address of s[1] and add 1 to that adress. You still need to dereference that: *(s[1]+1). Commented Feb 2, 2019 at 15:13
  • 1
    Doesn't your compiler give you a warning message? You have provided a pointer but %c expects the actual value. You need to de-reference the argument: *(s[1]+1) Commented Feb 2, 2019 at 15:13

2 Answers 2

1

The %c format specifier expects a character, not a pointer to a character. The expression s[1] evaluates to a pointer to a character, pointing to "Literal2", and the expression s[1]+1 also evaluates to a pointer to a character, pointing to "iteral2".

So, you are passing printf() a pointer to a character, and you are telling it to print a character. So, what is happening is that the pointer is being re-interpreted as a character, and the output is garbage.

If you insert a character into "String1", (making it, say, "String11",) then everything will be moved upwards in memory by one location, so the value of the pointer will be greater by 1, and so it might print n instead of m.

To obtain a character, when all you have is a pointer to a character, you need to dereference the pointer. So, that would be "%c", *(s[1]+1).

Sign up to request clarification or add additional context in comments.

2 Comments

Great explanation ! Only thing I can't understand is why does %c interpret the pointer as m. I thought it was something random but doing what you said (adding a character to the 0th string and moving everything up an adress) resulted in it being interpreted as n. That should mean that it isn't completely random, since you predicted it would, right ?(or was it just a coincidence?)
The pointer is a (32-bit or 64-bit) value which corresponds to a memory address. When you re-interpret a pointer as a character, you are taking the low-order 8 bits of that value and you are treating them as an ASCII value. Most chances are you will get something funny, like a control character. In your case it happened to be (by coincidence) a value within the alphabet, the letter 'm'. So, I figured that if the pointer is incremented by one, its low-order 8 bits will still be within the alphabet. Increment it by much, and you should see funny things.
0
#include <stdio.h>

int main() {
const char *s[] = {"String1", "Literal2", "Pointers3"}; 
printf("%c", s[1][1]);
return 0; }

Also i think you should make s[] constant as it's deprecated.

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.