Why does pointer arithmetic need to be cast?

Multi tool use
Why does pointer arithmetic need to be cast?
If I wanted to iterate over a string, in this case 'test', I could use pointer arithmetic like so to get to the next character:
char *c = "test";
*c++;
putchar(*c);
This would print the second letter 'e'.
But, if I wanted to go to the third character, why can't I say:
char *c = "test";
c = *c + 2; //*c = *c + 2; also doesn't work
putchar(*c); //Exception thrown: write access violation.
?
To my knowledge, the only way to get to the third character using pointer arithmetic is to cast it like so:
char *c = "test";
c = (char *) c + 2;
putchar(*c);
Can someone please explain to me why that is?
*
Yep. Dereference. Meaning, get the value associated with the memory address. For a string, dereferencing char * would give me the first character.
– sharkbites
Jul 3 at 9:09
In
c = *c + 2;
, you deference the value of c
ie the letter 't'
, add it 2
which means the value of the expression is the letter 'v'
(118), and then assign it to c. So when you do *c
in the last line, you want to access to the address 118
.– Paul Ankman
Jul 3 at 10:10
c = *c + 2;
c
't'
2
'v'
*c
118
@PaulAnkman that makes a lot of sense! Thanks
– sharkbites
Jul 3 at 10:12
4 Answers
4
c
here is a pointer which holds the address of a memory location.
c
*c
is called de-referencing the pointer which will give the value stored in the memory location pointed by c
.
*c
c
So
c = *c + 2
will be
c = (value stored at c) + 2;
which will not give the memory location like
c = c + 2;
so why does *c++ work?
– sharkbites
Jul 3 at 9:12
I hope you know what operator precedence is.
++
has higher precdence then *
so *c++
will be treated as c++
and later *c
– Gopi
Jul 3 at 9:14
++
*
*c++
c++
*c
There's an effective precedence of operators in C, described by the grammar in the standard.
++
"binds stronger" than *
, so happens first here. If you just write *c++;
, you effectively ignore the result of the dereference, but the side effect (incrementing c
) still happens. IOW, the *
in your *c++;
is nonsensical here, but doesn't hurt...– Felix Palmen
Jul 3 at 9:14
++
*
*c++;
c
*
*c++;
Why it shouldn't ? In
*c++
first c++
performed which means you are trying to change c
i.e address, which you can. Note that you can't do like (*c)++
or ++*c
here.– achal
Jul 3 at 9:18
*c++
c++
c
(*c)++
++*c
@sharkbites side note: you really shouldn't change the code in the question after you received answers. In this case, it doesn't make the answer appear wrong, so we can leave it, but please keep that in mind for the future :)
– Felix Palmen
Jul 3 at 9:20
In your first example, c++;
simply adds one to c
, no dereferencing, so why are you trying to dereference when adding 2? Simply add 2 to the pointer value:
c++;
c
char * c = "test";
c = c + 2; //*c = *c + 2; also doesn't work
putchar(*c);//Exception thrown: write access violation.
Your first code fragment was
char * c = "test";
*c++;
putchar(*c);
and as you noted, it prints e
. But it's important to note that in the second line, the *
is completely superfluous. You've incremented c
, and fetched the pointed-to-character -- and then thrown the pointed-to character away.
e
*
c
It would have worked exactly the same -- and been more clear, with no confusing, extra operators -- if you had instead said
char * c = "test";
c++;
putchar(*c);
Next you wondered why you couldn't increment the pointer by 2. But of course you can increment the pointer by two -- you could either say
char * c = "test";
c++;
c++;
putchar(*c);
or
char * c = "test";
c += 2;
putchar(*c);
or
char * c = "test";
c = c + 2;
putchar(*c);
But you wrote
c = *c + 2;
That didn't work, and no surprise -- again, you have an unnecessary *
, and here, it's not so harmless. Here, you unnecessarily fetch the character that c
points to, but instead of throwing it away, you add 2 to it, and then you try to assign the character to your original pointer variable. Your compiler probably complained about this -- assigning a character to a pointer is meaningless. It's as if you had said
*
c
c = 'x';
It looks like you may be unsure about what *
means in C. It is not just a marker that says "this variable is a pointer". It is an operator that actively fetches the value pointed to by the pointer.
*
Whenever you're working with pointers, you have to keep clear in your mind the very important distinction between the value of the pointer versus the value pointed to by the pointer.
Going back to your original example, when you said
char * c = "test";
the value of the pointer c
is "pointer to the first character of the string", and the value pointed to by the pointer is "the character t
".
c
t
If you say
c++
you increment the value of the pointer. Now it points at the second character of the string, and the value pointed to is the character e
.
e
If c
is a pointer, then any time I mention c
by itself in an expression, I am referring to the value of the pointer. But any time I stick the operator *
in front of it, I am referring to the value pointed to by the pointer.
c
c
*
I still dont get what you mean by " you have to keep clear in your mind the very important distinction between the value of the pointer versus the value pointed to by the pointer". In the example
char * c = "test";
, the pointer to the first character of the string is equal to 't', so isn't the "value of the pointer" and "value pointed to by the pointer" the same thing?– sharkbites
Jul 3 at 10:21
char * c = "test";
@sharkbites Perhaps this explanation will help: eskimo.com/~scs/cclass/notes/sx10.html
– Steve Summit
Jul 3 at 10:35
Lets understand the code below:
char * c = "test";
c = *c + 2; //*c = *c + 2; also doesn't work
putchar(*c);//Exception thrown: write access violation.
First statement says that you have an character array whose starting address is stored in variable c. Char are stored as ASCII value in memory.
Second statement says take value at address in location pointed to by c (ASCII of 'e' is 0x65) add 2 to it and save it as new address. Variable c now contains 0x67.
Third statement says print value as address stored in c (which is now 0x67). As we do not have access to this memory location an exception is thrown.
You would want to increment memory location pointed to by c and print the content. For that you would need to do:
char * c = "test";
c = c + 2; //Moves the pointer by 2 bytes
putchar(*c); //Print the character at that memory location
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Do you know the different meanings of the symbol
*
?– user202729
Jul 3 at 9:07