Shouldn't the output of the following code be f
I get an output e
#include<stdio.h>
void main(){
char arr[]="Geeks";
char *ptr = arr;
++*ptr++;
printf("%c\n",*ptr);
}
No, it shouldn't. Your code increments the first character and then moves the pointer one forward. The pointer will point to the first e, and depending on your locale/character encoding, the first letter is most probably H. The expression is parsed according to precedence and associativity rules as:
++(*(p++))
Yes expression is parsed as ++*((ptr++)), first ptr++ is calculated but because it is postfix increment the new calculated value doesn't update the old value of ptr until the statement ends (;) . Next ++**( ptr++ ) is calculated on old value of ptr that result , G change to H. Now all work is done, the statement ends and ptr value is updated, that points to next element that is e.
Related
we are currently learning how Pointers work in C.
I have this very short code of a copymethod of Strings in C, that was given to us from a tutor. I tried to explain its function in my own words but I am unsure if I have understood it correctly and would appreciate if somebody could correct my mistakes and answer my questions about it.
void copy ( char ∗ source , char ∗ dest) {
while (∗dest++ = ∗source++);
}
"Copy is a function with 2 Paramaters source and dest, which are both pointers of type char. The function calls a while statement which sets the dereferenced dest, incremented by 1 * sizeof(char), equal to the dereferenced and incremented (by 1*sizeof(char)) source."
What exactly does the while statement do? From my understanding *dest means that I am getting the char which dest points to, is that correct? But why would a while statement only set 2 pointers equal to each other, I don't really get it.
I appreciate any help, thank you!
This is the terse way to write an implementation of strcpy.
It is equivalent to the longer, but easier to follow
while (*dest = *source) {
dest++;
source++;
}
*dest = *source copies one char from the source to the destination. The result is zero if a zero byte was copied, at which time the loop ends.
Adding the increment to the condition is possible because the pointer dereferenced is the pointer value before the increment.
First, you need to start evaluating the expressions from the inner to the outer side. An important thing is to take into consideration that the body of the loop is empty (the ; at the right parenthesis indicates that the loop is executing the null statement --do nothing--, so everything must happen in the test expression).
The expression in the while test is not a test for equity, but an assignment. The equals operator is written doubling the =, as in ==, while = is used to assign the value of the right subexpression to the variable on the left side.
The variable on the left side is *dest++. A bit complicated expression that includes a dereference operator * and an autoincrement operator ++. The ++ takes higher preference, so it is acted first: the pointer is incremented, and the value returned by this subexpression is the value of the pointer before it was incremented. This means that the value of the pointer being used is the one it had before the expression dest++ was evaluated, and the * operator states the char variable pointed to by dest. So the place where the value will be stored in the assignment is the value pointed to by dest, and the pointer will be incremented before the end of the whole expression ends --but after the value is used--. The right side of the assignment show what is going to be assigned. As the expression is the same, I will pass quickly over it. The value assigned is the one pointed to by the source variable. It is incremented once the value is taken, and the value stored in the place of dest is filled with the character of the variable pointed by src. After that, both pointers are incremented, so the next time the test expression is evaluated, the characters involved will be the next source assigned to the next destination character. So, in this point, when the loop will be finished? Well, the value of an assignment expression is precisely the value assigned to the destination target, so in this case is the character copied from source to destination. And the test will fail, when the character copied happens to be zero (or false in C terms). As you see, there's nothing left to be put in the body of the loop.
This sample is famous for being an example of how cryptic C can get to. It appears in the two editions of "The C programming language" of Kernighan & Ritchie, the inventors of the language, and is accompanied by a comment that says something more or less like this: This is a bit obscure but every programmer that is proud of being proficient at C coding must be capable of interpreting this with a bit of care. (indeed the loop variables in the source are one letter s and d, i think)
This question already has answers here:
Pointer expressions: *ptr++, *++ptr and ++*ptr
(11 answers)
Closed 2 years ago.
I'm currently learning about pointers in C, but I'm a little confused about how right to left associativity works with regards to incrementing a pointer versus incrementing the value being pointed at.
It is understood that ++ and * are both right to left associative in C.
I don't see how *s++ moves the array ahead 1, yet (*s)++ increments the value being pointed at but doesn't move the array ahead.
For example:
#include <stdio.h>
int main(){
char c[20] = "Help";
char *s;
s = c;
printf("init: %s\n",s); // Help
++*s;
printf("++*s: %s\n",s); // "Ielp" ascii increment of first element
++(*s);
printf("++(*s): %s\n",s); // "Jelp" ascii increment of first element
*s++;
printf("*s++: %s\n",s); // "elp" moves to next element in array
(*s)++;
printf("(*s)++: %s\n",s); // "flp" ascii increment of current element
*(++s);
printf("*(++s)\n: %s\n",s); // "lp" moves to next element
*++s;
printf("*++s\n: %s\n",s); // "p" moves to next element
return 0;
}
For the code above, can someone help explain what is going on AND why?
Thanks for taking a look.
As helped by dxiv and John Bode,
When parsing an expression, an operator which is listed on some row will be bound tighter (as if by parentheses) to its arguments than any operator that is listed on a row further below it. For example, the expression *p++ is parsed as *(p++), and not as (*p)++.
In the above expression the point worth noted is ++ is a postfix operator whose precedence(or priority) is greater than *(unary operator)
Operators that are in the same cell (there may be several rows of operators listed in a cell) are evaluated with the same precedence, in the given direction. For example, the expression a=b=c is parsed as a=(b=c), and not as (a=b)=c because of right-to-left associativity.
other example where associativity comes into picture is *++p
here * and ++(prefix operator) are having same precedence, so they will be evaluated as right to left.
I referred this link Pointer expressions: *ptr++, *++ptr and ++*ptr to understand pointer arithmetic.
Why the below code is going to infinite loop?
int main(){
int a[4] ={1,2,3,4};
int *ptr = a;
while (++*ptr){
printf("%d",*ptr);
}
}
Your code does not work for two reasons:
++*ptr increments the number, not the pointer
You are iterating an array instead of a C string
You can iterate a C string using while (*ptr++) expression for the loop condition. This little trick works for C strings because they are null terminated. In order to make it work for arrays you would need to put zero at the end of the array, and agree to not use zeros anywhere else in the array:
int a[4] ={1,2,3,4, 0};
int *ptr = a;
int last;
while (last = *ptr++) {
printf("%d", last);
}
Note that since we are incrementing the pointer in the header of the loop, we should store the last value pointed to by the pointer in a separate variable. Otherwise we'd skip over one array element.
in loop condition value is 0 that time only loop terminated but you just increment the first position of the array value so zero value will not occur.
The issue is in the following line. Your while will break only if the value of ++*ptr is false or 0. But it never becomes 0 or false.
++*ptr
so while(NON ZERO) will result in infinite loop.
The loop is "infinite" because the condition in the while statement is always true until you hit the maximum value int can hold and after that you get undefined behavior.
What happens in the line is:
while (++*ptr)
First the pointer is dereferenced *ptr, obtaining the value of the first element in the array a, then that value is incremented by one. And then that resulting value is evaluated, giving the true result.
The same happens on every loop, the pointer ptr keeps pointing to the same element, the first one ptr == &a[0] , and keeps incrementing the value of that element by one a[0] = a[0]+1.
You are incrementing the value of the corresponding 0th position. So the starting position value of array is incremented. So the loop executing infinitely. Make the while loop as following.
while(*(++ptr))
int my_array[] = {1,23,17,4,-5,100};
int *ptr;
int i;
ptr = &my_array[0]; /* point our pointer to the first
element of the array */
printf("\n\nptr = %d\n\n", *ptr);
for (i = 0; i < 6; i++)
{
printf("my_array[%d] = %d ",i,my_array[i]); /*<-- A */
printf("my_array[%d] = %d\n",i, *(ptr++)); /*<-- B */
}
Why does this display the same thing for both line a and b? It just displays all of the values in my_array in order (1, 23, 17, 4, -5, 100). Why does the '++' in line B not point ptr to the next element of the array before it is dereferenced? Even if you change that line to
printf("ptr + %d = %d\n",i, *ptr++); /*<-- B */
the output is the same. Why is this?
ptr++ increments ptr but returns the original value
++ptr increments and returns the new value
Hence the joke about c++ - it's one more than c but you use the original value = c
It seems you are puzzled by the fact that the parenthesis do not change the value returned as you expectd.
Maybe it would be clearer to you if you think it in English:
p++ means take the value of p, increment the value of p, return the initial value of p
so, *p++ would dereference the original value of p.
Considering that the value of (x) is the same as x, the value of (p++) is the same as p++.
Hence, *(p++) will dereference p, exactly as *p++ does.
It is evident from the naming post-increment and pre-increment. Meaning, the variable is incremented post the operation or before the operation.
A post-increment operator creates a temporary variable to store the current value and increments the variable (but returns the temporary variable with current value). In pre-increment operator, there is no temporary variable. The same variable is incremented and returned.
So using post-increment operator in the same statement, means using the current value of the variable and incrementing after this statement. Whereas post-increment operator means incrementing the variable and using it in the current statement.
In C there is a difference between post incrementing p++ and preincrementing ++p
p++ : uses the current value of p and then updates it
++P: updates the value of p and then uses it
hence your code should use ++ptr
There are 2 types of operators : Postfix and Prefix .
*ptr++ is postfix operator means first use and then increase
while ++ptr means prefix operator means first increase and then use.
if you add another printf with printing the value of just *ptr in your existing code you will notice the difference how the things go about.
To avoid this whole issue, write either of these alternatives:
++ptr;
printf("my_array[%d] = %d\n",i, *ptr);
or
printf("my_array[%d] = %d\n",i, *ptr);
++ptr;
This will yield the same number of instructions, but with the following major advantages:
Is now more readable and understandable.
If ptr would be used several times in the printf() statement, you need not worry about the order of evaluation of function parameters or operands, which are unspecified in the C language (with a few rare exceptions). Had you writted printf("%d %d", *++ptr, *++ptr); you can't know the result, as the code would then rely on order of evaluation, i.e. it contains a possibly severe bug.
I am confused about this code: (http://www.joelonsoftware.com/articles/CollegeAdvice.html)
while (*s++ = *t++);
What is the order of execution? Is *s = *t first done, and then are they each incremented? Or other way around?
Thanks.
EDIT: And what if it was:
while(*(s++) = *(t++));
and
while(++*s = ++*t);
while (*s++ = *t++);
From the precedence table you can clearly see ++ is having higher precedence than *. But ++ is used here as post increment operator, so the incrementation happens after the assignment expression. So *s = *t happens first, then s and t are incremented.
EDIT:
while(*(s++) = *(t++));
Is same as above. You are making it more explicit with the use of parenthesis. But remember ++ is still a post increment.
while(++*s = ++*t);
There is just one operator next to s. So * is applied first and on that result ++ is applied which results in the lvalue required error.
while(*++s = *++t);
Again just operator next to s,t. So the incrementation happens first followed by copy. So we are effectively skipping the copy of the first char from t to s.
You are right. *s = *t is done first, and then they are incremented.
The increment is a post-increment. Post not just because it comes after the variable being incremented, but also because it comes after the expression is evaluated. So the order of execution is
*s = *t
then s++ and t++
EDIT::
#chrisgoyal
Order of execution is an ambiguous term. There are two different things here. The syntactical order, and the semantics of the expression.
Syntactically, the operator ++ is applied first. If the *s is applied first, then the following is equivalent to what #Hogan said:
(*s)++ = (*t)++
Which is very different from Joel's sample.
The semantics of the operator ++ is that it is executed after the expression.
Hope that clarifies what I meat.
Actually, s++ and t++ are applied first. Don't forget that the post-fix operator is executed after the expression is done. Basically the operator ++ is applied for both, then *s = *t is executed.
In Post increment operation variable is used first and then after its gets modified.
So there are two forms of increment
++s // increment before using value
s++ // increment after using value
And the result of these can be dereferenced:
*++s // or...
*s++
This worked out really well on one of the very first machines for C to run on, the PDP-11, which had a register-indirect addressing mode that increment the register after. The following ops were available in hardware:
*--s // or
*s++
You could do either
*x++ = *y++; // or
*--x = *--y; // or some combination
And if you did, the whole line happened in a single instruction. Since // comments were introduced by C99, however, you couldn't actually get away with my comment syntax.
The code: (while *s++ = *t++); is roughly equivalent to:
while (*s = *t) {
++s;
++t;
}
The second is exactly the same -- the extra parens don't change anything (in this case). For the parens to do anything, they'd have to be like: while ((*s)++ = (*t)++);. This would do roughly the same as your third example (covered in the paragraph below).
The last example: while(++*s = ++*t); is completely different. Since the dereference (*) is closer to the operand, this dereferences the operand, and increments the result of the dereference, which means it increments what the pointer points AT, instead of incrementing the pointer itself. As a result, this would copy the first character, then increment that character, then check whether that character was non-zero and continue the same until it was zero. The result would be both the source and the destination becoming empty strings (since the first character of both would now be a zero, which is used to terminate strings).