How does "while(*s++ = *t++)" copy a string? - c

My question is, what does this code do (from http://www.joelonsoftware.com/articles/CollegeAdvice.html):
while (*s++ = *t++);
the website says that the code above copies a string but I don't understand why...
does it have to do with pointers?

It is equivalent to this:
while (*t) {
*s = *t;
s++;
t++;
}
*s = *t;
When the char that t points to is '\0', the while loop will terminate. Until then, it will copy the char that t is pointing to to the char that s is pointing to, then increment s and t to point to the next char in their arrays.

This has so much going on under the covers:
while (*s++ = *t++);
The s and t variables are pointers (almost certainly characters), s being the destination. The following steps illustrate what's happening:
the contents of t (*t) are copied to s (*s), one character.
s and t are both incremented (++).
the assignment (copy) returns the character that was copied (to the while).
the while continues until that character is zero (end of string in C).
Effectively, it's:
while (*t != 0) {
*s = *t;
s++;
t++;
}
*s = *t;
s++;
t++;
but written out in a much more compact way.

Let's assume s and t are char *s that point to strings (and assume s is at least as large as t). In C, strings all end in 0 (ASCII "NUL"), correct? So what does this do:
*s++ = *t++;
First, it does *s = *t, copying the value at *t to *s. Then, it does s++, so s now points to the next character. And then it does t++, so t points to the next character. This has to do with operator precedence and prefix vs. postfix increment/decrement.
Operator precedence is the order in which operators are resolved. For a simple example, look:
4 + 2 * 3
Is this 4 + (2 * 3) or (4 + 2) * 3? Well, we know it is the first one because of precedence - the binary * (multiplication operator) has higher precedence than the binary + (addition operator), and is resolved first.
In *s++, we have unary * (pointer dereference operator) and unary ++ (postfix increment operator). In this case, ++ has higher precedence (also said to "bind tighter") than *. If we had said ++*s, we would increment the value at *s rather than the address pointed to by s because prefix increment has lower precedence* as dereference, but we used postfix increment, which has higher precedence. If we had wanted to use prefix increment, we could have done *(++s), since the parenthesis would have overridden all lower precedences and forced ++s to come first, but this would have the undesirable side effect of leaving an empty character at the beginning of the string.
Note that just because it has higher precedence doesn't mean it happens first. Postfix increment specifically happens after the value has been used, which his why *s = *t happens before s++.
So now you understand *s++ = *t++. But they put it in a loop:
while(*s++ = *t++);
This loop does nothing - the action is all in the condition. But check out that condition - it returns "false" if *s is ever 0, which means *t was 0, which means they were at the end of the string (yay for ASCII "NUL"). So this loop loops as long as there are characters in t, and copies them dutifully into s, incrementing s and t all the way. When this loop exits, s has been NUL-terminated, and is a proper string. The only problem is, s points to the end. Keep another pointer handy that points to the beginning of s (i.e. s before the while() loop) - that will be your copied string:
char *s, *string = s;
while(*s++ = *t++);
printf("%s", string); // prints the string that was in *t
Alternatively, check this out:
size_t i = strlen(t);
while(*s++ = *t++);
s -= i + 1;
printf("%s\n", s); // prints the string that was in *t
We started by getting the length, so when we ended, we did more pointer arithmetic to put s back at the beginning, where it started.
Of course, this code fragment (and all my code fragments) ignore buffer issues for simplicity. The better version is this:
size_t i = strlen(t);
char *c = malloc(i + 1);
while(*s++ = *t++);
s -= i + 1;
printf("%s\n", s); // prints the string that was in *t
free(c);
But you knew that already, or you'll soon ask a question on everyone's favorite website about it. ;)
* Actually, they have the same precedence, but that's resolved by different rules. They effectively have lower precedence in this situation.

while(*s++ = *t++);
Why do people think it is equivalent to:
while (*t) {
*s = *t;
s++;
t++;
}
*s = *t; /* if *t was 0 at the beginning s and t are not incremented */
when it obviously isn't.
char tmp = 0;
do {
tmp = *t;
*s = tmp;
s++;
t++;
} while(tmp);
is more like it
EDIT: Corrected a compilation error. The tmp variable must be declared outside of the loop.

The aspect that is mysterious about this is the order of operations. If you look up the C language spec, it states that in this context, the order of operations is as follows:
1. * operator
2. = (assignment) operator
3. ++ operator
So the while loop then becomes, in english:
while (some condition):
Take what is at address "t" and copy it over to location at address "s".
Increment "s" by one address location.
Increment "t" by one address location.
Now, what is "some condition"? The C lang specification also says that the value of an assignment expression is the assigned value itself, which in this case is *t.
So "some condition" is "t points to something that is non-zero", or in a simpler way, "while the data at location t is not NULL".

The C Programming Language (K&R) by Brian W. Kernighan and Dennis M. Ritchie gives a detailed explanation of this.
Second Edition, Page 104:
5.5 Character Pointers and Functions
A string constant, written as
"I am a string"
is an array of characters. In the internal representation, the array is terminated with the null character '\0' so that programs can find the end. The length in storage is thus one more than the number of characters between the double quotes.
Perhaps the most common occurrence of string constants is as arguments to functions, as in
printf("hello, world\n");
Where a character string like this appears in a program, access to it is through a character pointer; printf receives a pointer to the beginning of the character array. That is, a string constant is accessed by a pointer to its first element.
String constants need not be functions arguments. If pmessage is declared as
char *pmessage;
then the statement
pmessage = "now is the time";
assigns to pmessage a pointer to the character array. This is not a string copy; only pointers are involved. C does not provide any operators for processing an entire string of characters as a unit.
There is an important different between these definitions:
char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed by amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.
+---+ +--------------------+
pmessage: | o-------->| now is the time \0 |
+---+ +--------------------+
+--------------------+
amessage: | now is the time \0 |
+--------------------+
We will illustrate more aspects of pointers and arrays by studying versions of two useful functions adapted from the standard library. The first function is strcpy(s,t), which copies the string t to the string s. It would be nice just to say s = t but this copies the pointer, not the characters.To copy the characters, we need a loop. The array version is first:
/* strcpy: copy t to s; array subscript version */
void strcpy(char *s, char *t)
{
int i;
i = 0;
while((s[i] = t[i]) != '\0')
i ++;
}
For contrast, here is a version of strcpy with pointers:
/* strcpy: copy t to s; pointer version 1 */
void strcpy(char *s, char *t)
{
while((*s = *t) != '\0')
{
s ++;
t ++;
}
}
Because arguments are passed by value, strcpy can use the parameters s and t in any way it pleases. Here they are conveniently initialized pointers, which are marched along the arrays a character at a time, until the '\0' that terminates t has been copied to s.
In practice, strcpy would not be written as we showed it above. Experienced C programmers would prefer
/* strcpy: copy t to s; pointer version 2 */
void strcpy(char *s, char *t)
{
while((*s++ = *t++) != '\0')
;
}
This moves the increment of s and t into the test part of the loop. The value of *t++ is the character that t pointed to before t was incremented; the postfix ++ doesn't change t until after this character has been fetched. In the same way, the character is stored into the old s position before s is incremented. This character is also the value that is compared against '\0' to control the loop. The net effect is that characters are copied from t to s, up to and including the terminating '\0'.
As the final abbreviation, observe that a comparison against '\0' is redundant, since the question is merely whether the expression is zero. So the function would likely be written as
/* strcpy: cope t to s; pointer version 3 */
void strcpy(char *s, char *t)
{
while(*s++ = *t++);
}
Although this may seem cryptic as first sight, the notational convenience is considerable, and the idiom should be mastered, because you will see if frequently in C programs.
The strcpy in the standard library (<string.h>) returns the target string as its function value.
This is the end of the relevant parts of this section.
PS: If you enjoyed reading this, consider buying a copy of K&R - it is not expensive.

It works by copying characters from the string pointed to by 't' into the string pointed to by 's'. For each character copies, both pointers are incremented. The loop terminates when it finds a NUL character (equal to zero, hence the exit).

HINTS:
What does the operator '=' do?
What is the value of the expression "a = b"? Eg: if you do "c = a = b" what value does c get?
What terminates a C string? Does it evaluate true or false?
In "*s++", which operator has higher precedence?
ADVICE:
Use strncpy() instead.

it copies a string because arrays are always passed by reference, and string is just a char array. Basically what is happening is (if i remember the term correctly) pointer arithmetic. Here's a bit more information from wikipedia on c arrays.
You are storing the value that was dereferenced from t in s and then moving to the next index via the ++.

Say you have something like this:
char *someString = "Hello, World!";
someString points to the first character in the string - in this case 'H'.
Now, if you increment the pointer by one:
someString++
someString will now point to 'e'.
while ( *someString++ );
will loop until whatever someString points at becomes NULL, which is what signals the end of a string ("NULL Terminated").
And the code:
while (*s++ = *t++);
is equal to:
while ( *t != NULL ) { // While whatever t points to isn't NULL
*s = *t; // copy whatever t points to into s
s++;
t++;
}

Yes, it does have to do with pointers.
The way to read the code is this: "the value that is pointed to by the pointer "s" (which gets incremented after this operation) gets the value which is pointed to by the pointer "t" (which gets incremented after this operation; the entire value of this operation evaluates to the value of the character copied; iterate across this operation until that value equals zero". Since the value of the string null terminator is the character value of zero ('/0'), the loop will iterate until a string is copied from the location pointed to by t to the location pointed to by s.

Many adherents of С language are convinced that the "while (* s ++ = * t ++)"
is a genuine grace.
In the conditional expression of the loop "while",three side effects are inserted(shift of one pointer, shift of the second pointer, assignment).
The body of the loop as a result was empty, since all the functionality is placed in a conditional expression.

use for with int i:
char t[]="I am a programmer",s[20];
for(int i=0;*(t+i)!='\0';i++)
*(s+i)=*(t+i);
*(s+i)=*(t+i); //the last char in t '\0'
printf("t is:%s\n",t);
printf("s is:%s\n",s);
use for with pointer++:
char t[]="I am a programmer",s[20];
char *p1,*p2;
p1=t,p2=s;
for(;*p1!='\0';p1++,p2++)
*p2 = *p1;
*p2 = *p1;
printf("t is:%s\n",t);
printf("s is:%s\n",s);
use while with pointer++:
char t[]="I am a programmer",s[20];
char *p1,*p2;
p1=t,p2=s;
while(*p2++=*p1++);
printf("t is:%s\n",t);
printf("s is:%s\n",s);
printf("t is:%s\n",p1-18);
printf("s is:%s\n",p2-18);
use array to initialize pointers:
char a[20],*t="I am a programmer",*s;
s=a;
while(*s++=*t++);
printf("t is:%s\n",t-18);
printf("s is:%s\n",s-18);
printf("s is:%s\n",a);

starts a while loop....
*s = *t goes first, this assigns to what t points at to what s points at. ie, it copies a character from t string to s string.
what is being assigned is passed to the while condition... any non zero is "true" so it will continue, and 0 is false, it will stop.... and it just happens the end of a string is also zero.
s++ and t++ they increment the pointers
and it all starts again
so it keeps assigning looping, moving the pointers, until it hits a 0, which is the end of the string

Yes this uses pointers, and also does all the work while evaluating the while condition. C allows conditional expressions to have side-effects.
The "*" operator derefereces pointers s and t.
The increment operator ("++") increments pointers s and t after the assignment.
The loop terminates on condition of a null character, which evaluates as false in C.
One additional comment.... this is not safe code, as it does nothing to ensure s has enough memory allocated.

The question I provided the following answer on was closed as a duplicate of this question, so I am copying the relevant part of the answer here.
The actual semantic explanation of the while loop would be something like:
for (;;) {
char *olds = s; // original s in olds
char *oldt = t; // original t in oldt
char c = *oldt; // original *t in c
s += 1; // complete post increment of s
t += 1; // complete post increment of t
*olds = c; // copy character c into *olds
if (c) continue; // continue if c is not 0
break; // otherwise loop ends
}
The order that s and t are saved, and the order that s and t are incremented may be interchanged. The save of *oldt to c can occur any time after oldt is saved and before c is used. The assignment of c to *olds can occur any time after c and olds are saved. On the back of my envelop, this works out to at least 40 different interpretations.

Well this is true just in the case of the char if there is no \0 and the it is an integer array the the program will crash because there will be a address whose elements are not the part of the array or pointer, if the system has memory that was allocated using the malloc then the system will keep giving the memory

Related

Is there any benefit of using pointer arithmetic on character array in C?

I have a question regarding the operation on character array.
I was inspired by This answer here that discusses char* vs char[]. In this answer, it says considering a case where we want to cut off the first character of a word,
char* p = "hello";
p++;
is a much faster operation, than if we declared using character array, and therefore had to index into every element.
char s[] = "hello";
s[0] = 'e';
s[1] = 'l';
s[2] = 'l';
s[3] = 'o';
s[4] = '/0';
But my question is, in the second case, cannot I just use another pointer that points to the start of s, i.e.
char* ptr = s;
and then treat it the same as char* p? Would it be as fast?
You mean something like this?
char s[] = "Hello";
char *ptr = s+1;
Yes, you can do that, and it results in ptr pointing to the string "ello". It is just as fast; like the other example, it should be simple arithmetic and not require any copying of data.
I think it is a misconception to think of this as a "pointer versus array" issue. Pointers and arrays in C are inseparable. Both examples involve an array, and two different pointers into that array. In the first example, the array is created by the string literal "Hello" and doesn't have a name; the values of p before and after p++ both point into that array. In the second example, the array is named s, and the expression s decays into a pointer to the zeroth element of that array; s+1 is a pointer to the first element.
The main difference is that in the second example, the array can be modified, and may have a finite lifetime. So your program now has to manage issues of aliasing and ownership. Suppose one part of the code accesses the string through s, and another part accesses it through ptr. Are you prepared for the fact that if the first code modifies the string, the second code will see it change? Does your code correctly keep track of when the lifetime of s ends (e.g. the end of the block where it's defined), and does it make sure not to use ptr beyond that point?
By contrast, the string literal in the first example has static lifetime, and survives until the end of the program; so ptr = p+1 remains valid indefinitely. It also must not be modified at all, or undefined behavior results. So if your program is otherwise bug free, you don't have to worry about some other part of your code changing the string behind your back.
The way I understand these things:
char *p = "hello";
Six bytes (including terminating '\0') are put in READ ONLY memory, and the address of the first byte is put into the variable p that has the datatype char *. Yes, the code can increment/decrement p to point further into the string.
char s[] = "hello";
Six bytes (including terminating '\0') are put in READ/WRITE memory, and referring to s means referring to the initial byte of the string. Yes, another pointer can be declared: char *p = s; And, yes, the code can manipulate the data stored in those six bytes.
char *p = &s[1]; // don't need to increment.
If you want to really play with things:
printf( "%.3s\n", &"Hi there"[3] );
will print "the". There is no name and no pointer, but there is an unnamed READONLY array that can be (carefully!) accessed.
Consider the following example that 'decorates' up to the 31 day of a month with the correct 'ordinal' suffix:
for( int DoM = 1; DoM <= 31; DoM++ ) {
int i = DoM;
if( i > 20 ) i %= 10; // Change 21-99 to 1-10. Don't wanna think about 100+
if( i > 3 ) i = 0; // Every other one ends with "th"
// 0 1 2 3
printf( "%d%s\n", DoM, &"th\0st\0nd\0rd"[ i * 3 ] );
}

Pointers in C, I'm so confused

Currently I'm following this pdf on C pointers. The code below was meant as a demonstration but confused me beyond belief. Firstly, my understanding of pointers to arrays is that they are initialized in heap memory with the memory address of the first element in the array hence why: ptr = &my_array[0]; /* and */ ptr = my_array; are the same thing. My first issue with this code is that he created a pointer that doesn't point to a memory address. I thought pointer initialization would usually involve the & and the value of pA would be the memory address of the first element of the array, but when he prints the pointer to the screen THE WHOLE STRING PRINTS OUT. Why? On top of that, when I put another * on pA it prints the first character of the array. Why? On top of that, he uses ++ on *pA and *pB which makes no sense to me because the output shows that *pA is the first character in the array not a memory address.
Sorry this concept has been tough for me to wrap my head around. Is the PDF just bad at explaining pointers or am I grossly misunderstanding something?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char strA[80] = "A string to be used for demonstration purposes";
char strB[80];
int main(int argc, char *argv[]){
char *pA; /* a pointer to type character */
char *pB; /* another pointer to type character */
puts(strA); /* show string A */
pA = strA; /* point pA at string A */
puts(pA); /* show what pA is pointing to */
pB = strB; /* point pB at string B */
putchar('\n'); /* move down one line on the screen */
printf("\n%c\n", *pA);
while(*pA != '\0') /* line A (see text) */
{
*pB++ = *pA++; /* line B (see text) */
}
*pB = '\0'; /* line C (see text) */
puts(strB); /* show strB on screen */
return 0;
}
Output:
A string to be used for demonstration purposes
A string to be used for demonstration purposes
A
A string to be used for demonstration purposes
EDIT:
Thanks for the help everyone :), sorry about the noobie question. I read Programming in C by Stephen G. Kochan and its amazing section on pointers helped a lot.
char strA[80] = "A string to be used for demonstration purposes";
This makes an 80 character long space in the global section of the executable - it isn't dynamically allocated so it doesn't need to be deallocated. If strA is used as a pointer it is equivalent to &strA[0] as you expect.
Those 80 characters are filled with the string on the right side of the equals - including the terminating character at the end of the string. That terminating character is really important because that's how you find the end of the printable data in the array.
puts(strA); /* show string A */
When you puts(strA), that function prints EVERY character from the address passed in up to that terminating character - there is a loop inside that function.
pA = strA; /* point pA at string A */
puts(pA); /* show what pA is pointing to */
Then pA is filled with the value of &strA[0] and then when puts(pA); is called, the function receives the same address it received the last time so it does the same thing as last time: it prints EVERY character from the address passed in up to that terminating character.
printf("\n%c\n", *pA);
while(*pA != '\0') /* line A (see text) */
The * character gives you the contents at the location of the pointer - so *strA gives the same thing as strA[0] - the first character of the string. And *pA is the same as *strA because they both point to the same address.
*pB++ = *pA++; /* line B (see text) */
The reason *pA++ confuses you is because you don't know whether the * or the ++ is done first. What happens is: pA++ increments the pointer and returns the original value it had. Then the * takes that original value of the pointer and gives its content - the character where pA originally pointed.
According to the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
So these two assignment statements
ptr = &my_array[0];
and
ptr = my_array;
are equivalent because the array designator my_array used as an initializer is implicitly converted to pointer to its first element.
In C strings are character arrays that contain sequences of characters terminated with the zero terminating character '\0'.
For example the string literal "Hello" is stored as a character array with this sequence of characters
{ 'H', 'e', 'l', 'l', 'o', '\0' }
The function puts is specially designated to output strings.
It is declared the following way
int puts(const char *s);
the calls of the function
puts(strA);
puts(pA)
are equivalent because again the array designator strA used as an argument in the first call is implicitly converted to pointer to its first element.
Dereferencing a pointer like in this call
printf("\n%c\n", *pA);
you get the object pointed to by the pointer. As the pointer pA points to the first character of the array strA then this character is outputted.
As a follow up to Vlad's answer, which is great, I just wanted to add a small bit of code which really helped me to understand pointers. I find that it is really helpful to make predictions and then write code and make observations until I understand.
[ttucker#zim stackoverflow]$ cat ptr.c
#include <stdio.h>
int main() {
char *foo = "stuff";
while (*foo != '\0') {
printf("%lu: %c (%d), %lu\n", &foo, *foo, *foo, foo);
foo++;
}
return 0;
}
[ttucker#zim stackoverflow]$ gcc -o ptr ptr.c
[ttucker#zim stackoverflow]$ ./ptr
140730183740528: s (115), 94216543457284
140730183740528: t (116), 94216543457285
140730183740528: u (117), 94216543457286
140730183740528: f (102), 94216543457287
140730183740528: f (102), 94216543457288
# A second execution is included to show that the memory addresses change.
[ttucker#zim stackoverflow]$ ./ptr
140723360085232: s (115), 94198997999620
140723360085232: t (116), 94198997999621
140723360085232: u (117), 94198997999622
140723360085232: f (102), 94198997999623
140723360085232: f (102), 94198997999624
Firstly, my understanding of pointers to arrays is that they are initialized in heap memory with the memory address of the first element in the array hence why: ptr = &my_array[0]; /* and */ ptr = my_array; are the same thing.
The only time "heap" memory comes into play is when you're using malloc, calloc, or realloc, or library functions that call them behind the scene. pA and pB occupy the same memory as any other type of variable declared in that scope.
but when he prints the pointer to the screen THE WHOLE STRING PRINTS OUT.
The puts function takes the address of the first character in a string and "walks" down the string, printing each character, until it sees the string terminator, sort of like
void myputs( const char *str ) // str points to the first character in a 0-terminated string
{
while ( *str ) // while we haven't seen the string terminator
putchar( *str++ ); // print the current character and advance the pointer
}
On top of that, he uses ++ on *pA and *pB which makes no sense to me because the output shows that *pA is the first character in the array not a memory address.
The line
*pB++ = *pA++;
is roughly equivalent to writing:
*pB = *pA;
pB = pB + 1;
pA = pA + 1;
Postfix ++ has higher precedence than unary *, so *pA++ is parsed as *(pA++) - you're dereferencing the result of pA++. The result of pA++ is the current value of pA, and as a side effect pA is incremented. Since pA and pB are pointers, adding 1 advances them to point to the next object in the sequence, not necessarily the next byte (although in this particular case, the next object is the next byte).

Do functions w/pointer arguments still have local copies of those arguments?

Consider the following code taken from K&R:
/* strlen: return length of string s */
int strlen(char *s)
{
int n;
for (n = 0; *s != '\0', s++)
n++;
return n;
}
K&R states that here "s++ has no effect on the character string in the function that called strlen, but merely increments strlen's private copy of the pointer".
Am I correct in interpreting "s++" as being equivalent to "&s[0]+1". This seems non-sensical to me, so I must be wrong here.
If s++ really has no effect on *s, then how could the loop condition (i.e., *s != '\0') ever change in truth value? After all, *s is unaffected by s++. So it will either be true forever or false in the first place. Why is this not the case?
Am I correct in interpreting "s++" as being equivalent to "&s[0]+1".
No. The expression &s[0]+1 does not have side-effects - s++ does. The way it is used here (that is without using its return value), s++ is equivalent to s = s + 1 or s = &s[0]+1 or s = &s[1] (which all do the same thing).
If s++ really has no effect on *s, then how could the loop condition (i.e., *s != '\0') ever change in truth value?
s++ does have an effect on *s in the sense that it changes what s points to and if s points to somewhere else, then of course the value of the expression *s will change. However it does not have an effect on the value that s previously pointed to.
To illustrate this consider strlen being called on a string str where char* str = "abcd";: At the beginning of the loop s points to str[0]and thus *s is equal to 'a' because str[0] is equal to 'a'. After you do s++, s now points to str[1]. Now *s is equal to 'b' because str[1] is equal to 'b', yet neither str[0] nor the contents of str changed.
A copy of the pointer, yes. Arguments are always copied. And the same way a function can modify arguments as its own local variables without affecting the original variable, the same can be done with pointers.
By incrementing s++ you are doing the same as s = &s[1] or s = s + 1, and it modifies s as the local variable it is, this change does not propagate to the original pointer in the caller.
Only by modifying the value a pointer is pointing to, as when modifying *s, it will have it modified in the caller aswell. Thats why when attempting to modify a pointer itself, you have to use a pointer to a pointer, for instance: char** var

What does the "++" operator do on a "char *"?

In the following function:
double dict(const char *str1, const char *str2) {
There is the following:
if (strlen(str1) != 0 && strlen(str2) != 0)
while (prefix_length < 3 && equal(*str1++, *str2++)) prefix_length++;
What does the operator ++ do in *str1++ and *str2++?
The ++ operator in *str++ increments the pointer (not the thing pointed at).
(*str)++; /* Increment the character pointed at by str */
*str++; /* Increment the pointer in str */
*(str++); /* Increment the pointer in str - the same, but verbose */
There are two very different operations shown (one of them shown using two different but equivalent notations), though they both return the character that str pointed at before the increment occurs. This is a consequence of the precedence rules in the standard — postfix operators like ++ have higher precedence than unary (prefix) operators like * unless parentheses are used to alter this.
When you read or write to *str1++, the normal rules for postfix increment are applied. That is:
The pointer is incremented to the next address
The previous pointer value is returned
At that stage you dereference the pointer value (which is the value prior to incrementing) and use the value it points to.
*str1++ means first use the value pointed by str1 and then increment str1.
char arr[] = "meow";
char ch;
char *str = arr;
ch = *str++; // ch = *(str++) both does same
After executing the statement above:
ch will contain 'm';
str will point to the address of arr[1].
in C (and some derived languages) the char type is also a number type (a small one that can contains 256 different values), so you can do arithmetic operations on it, like addition (+2), increment (++) and so on.
in this case, the ++ operator doesn't increment the char but the pointer to this char.
*str2++ returns the next address of the pointer to str2

Incrementing the lvalue of a pointer to char?

My question is simple:
Say you have this:
char *chrptr = "junk";
Imagine at the time, *chrptr would point at j. Is there a way to increment the current character j to the next character which, in this case would be k? I don't want to go to the next character, I want to increment the current-pointed to character.
I'm new to C, and what I tried: (*chrptr)++ doesn't work.
Based on your edit, it seems like you want to modify the string, you can't do that with a constant string, actually you can but that behaviour is undefined. So you need to change the definition to a non-constant array of characters:
//This initializes a 5 element array including the null byte at the end
char chrptr[] = "junk";
//now you can modify that
chrptr[0]++;
//or equivalently
chrptr[0] +=1;
chrptr[0] = chrptr[0]+1;
char *chrptr = "junk";
This code isn't really good. String literals like "junk" are pointers to read-only memory. You're not supposed to ever modify them. So either say:
const char* chrptr = "junk"; // pointer to a const; no modifications
or (in your case):
char chrArray[] = "junk";
This creates a 5-element array of characters on the stack, initializes it with "junk" (plus the null terminator). Now you're free to modify it:
chrArray[0] ++;
(*chrArray) ++;
(Some leftover remarks)
I'm new to c, but things such as (*chrptr)++ don't work.
They do work, but differently. Let me sum this up:
chrptr is a value of type pointer-to-char.
*chrptr is a value of type char, because the pointer has been dereferenced.
Both of these happen to be "l-values" (= actual objects), so you can modify them:
++ chrptr increments the pointer by one (= advances the pointer one object forward)
++ *chrptr increments the char by one (= changes 'a' into 'b').
(Before, ++*chrptr didn't work for you because the string was in read-only section of memory. If you had pointed to it using const char* not char*, you'd get a helpful compile error instead of unexpected runtime behaviour.)
Also note:
In case of a simple statement, ++*chrptr; is equivalent to (*chrptr)++;. The operator order is important (dereference, then increment).
OTOH, *chrptr++ is increment-then-dereference because of the operator precedence. If not sure about precedence, add parentheses.
You do not need to dereference the pointer again using the dereference operator *.
You simply need to do chrptr++ to advance the character pointer in memory.
Update
You can wrap a while loop around to search for the character.
char *chrptr = "junk";
char search = 'k';
while (*chrptr) {
if (*chrptr == search)
printf("%c\n", *chrptr);
chtptr++;
}
See this (*chrptr)++; works fine but this will increment the first character of the array pointed by chrptr.
In your case you are using the statement like
char *chrptr = "junk";
Here chrptr is pointing to a const char array so on using (*chrptr)++; it will increment not reflect the changes in the string.
But if you use the code like this way (http://codepad.org/FJMB1ryv) :--
#include<iostream>
using namespace std;
int main()
{
char a[]="yogendra";
char *y=a;//(char*)"junk";
(*y)++;
cout<<y<<endl;
return 0;
}
you (*y)++ will work.Hoping this will help you. Good luck:)

Resources