Does this contain a sequence point? - c

In the recent post C string to uppercase in C and C++, the function:
void strupp(char* beg)
{
while (*beg++ = toupper(*beg));
}
showed the undesirable result of 'OOBAR' when given 'foobar' with an answer explaining "there is no sequence point" in the expression. Now I have always been using
char *s1=strTo, *s2= strFrom;
while (*s2) *s1++ = *s2++;
with the understanding it means to get the value of the right part (*s2), increment s2; assign the obtained value to *s1 and increment s1. But it seems that this neither contains a sequence point so that it has always worked would be coincidence (luck), which I can't believe.
Anyone can help me and explain this?

The outcome of
while (*beg++ = toupper(*beg));
depends on whether the LHS is evaluated first or the RHS is evaluated first.
The outcome of
while (*s2) *s1++ = *s2++;
does not depend on whether the LHS is evaluated first or the RHS is evaluated first.
That is the crucial difference. Hence, lack of a sequence point matters in the first case but does not matter in the second case.

The result of your operation:
*s1++ = *s2++;
does not depend on when the increments are done. So the absense of the sequence point doesn't pose any problems.

Related

What does a while statement that only sets 2 pointers equal, do?

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)

Precedence of arr[x++]--

I am confused on how to parse precedence of operations in C. the line
countArray[*string++]--
Is executing how I want it to, but I don't understand the steps that result in countArray[*string]-- being evaluated before *string++.
My research on C precedence and binding didn't provide answers that relate to this case, and I'm wondering about general rules for post/pre-increment and post/pre-decrement when in combination with other post/pre - crements.
How does C know to evaluate it this way?
void discountChars(char* string, char** countArray)
{
int test;
while(*string) {
test = *string;
//why is countArray[*string]-- evaluated before string++ is incremented?
countArray[*string++]--;
printf("countArray[%d] = %d\n", test, countArray[test]);
}
}
You can break this:
countArray[*string++]--;
down into this:
char index = *string; // get char from `string` into temporary index
string++; // increment `string`
countArray[index]--; // decrement `countArray` value at given index
and then it should be clearer what's going on.
As it has been stated many times, precedence has no connection to the order of evaluation. The only thing in C language that can affect order of evaluation is sequencing. Precedence has nothing to do with it.
It is also unclear where you got the strange idea that "countArray[*string]-- is being evaluated before *string++". This is simply impossible. The expression in [] will always be evaluated first, since its result is required to perform the element access (i.e. sequenced before the element access). Which means that the opposite is true: *string++ is evaluated before countArray[*string]--.
So, the sequence of steps here is
Evaluate *string++. The result of this expression is the original value of *string. Let's designate it tmp.
This expression also "schedules" a side-effect - increment of string. But this increment does not have to happen right now.
Evaluate countArray[tmp]--. The result of this expression is the original value of countArray[tmp]. This result is immediately discareded.
This expression also "schedules" a side-effect - decrement of countArray[tmp]. But this decrement does not have to happen right now.
Complete the evaluation of the full expression . If any of the above side-effects are still pending, complete them right now.
For example, one possible evaluation schedule might look as follows
char tmp = *string; // subexpression inside `[]`
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
string = string + 1; // side-effect
Another possible evaluation schedule is
char tmp = *string; // subexpression inside `[]`
string = string + 1; // side-effect
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
It can even be evaluated as
string = string + 1; // side-effect
char tmp = *(string - 1); // subexpression inside `[]`
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
Precedence controls groupings of operators and operands, not order of evaluation.
The expression *string++ must be evaluated before it can be used as an array subscript; however, the side effect of updating string may happen after the larger expression has been evaluated. The following sequence of events is allowed:
t1 <- *string
countArray[t1] <- countArray[t1] - 1
string <- string + 1
Then again, so is the following:
t1 <- *string
string <- string + 1
countArray[t1] <- countArray[t1] - 1

C pointer sum "not working"

I do not understand what is the point in the else sentence *nombre=(*nombre)++.
Output shows "fernando" and what i thought it was going to show was "ffsoboep" because of the sum. But it seems that *nombre=(*nombre)+1 is different to *nombre=(*nombre)++;
My question is why is that happening? how does "++" operator works in that case. Thanks.
void recursiva (char * nombre)
{
if (*nombre != '\0')
{
recursiva(nombre+1);
if(*nombre > 'A' && *nombre < 'Z')
{
*nombre=*nombre | 32;
}
else
{
*nombre=(*nombre)++;
printf("%c \n",*nombre);
}
}
}
int main()
{
char nombre[]="Fernando";
recursiva(nombre);
printf("%s",nombre);
}
(*nombre)++
doesn't mean the same thing as
*nombre + 1
It means "return the original value of *nombre, with the side effect of increasing *nombre's value by 1". Note that when exactly the value of *nombre increases is rather vague; while it happens after the value of (*nombre)++ is computed, it might happen before, after, or during the assignment to *nombre, with unpredictable results.
If you want to increase the value of *nombre, you don't need to assign the value of (*nombre)++ back to *nombre, and in fact, trying to do so is undefined behavior. As a first approximation, the program is allowed to do anything, up to and including making demons fly out your nose. Just use ++:
(*nombre)++;
or += 1:
*nombre += 1;
I ran your code and actually got "ffsoboep".
If you see that in other compilers you get "fernando", I believe that the following point is not defined in the standard:
*nombre=(*nombre)++;
This is post increment. The value of (x++) is the value of x before the increment (i.e., x == x++ is true).
The question is when does the increment is done.
If the increment is done immediately or after the evaluation of the right side of the = expression, then you first increment the value, and then re-assign the value of the expression (*nombre)++ (which is the value before the increment) to the already incremented *nombre.
If the increment is done, after all the expression is evaluated, then you first assign the (same) value to *nombre, and only then increment.
I think this is not defined in the standard, and therefore - you might see different behaviours. I encountered similar case in the past.

Arithmetic operations in IF loop

What does the below code do? I'm very confused with its working. Because I thought that the if loop runs till the range of int. But I'm confused when I try to print the value of i. Please help me out with this.
#include<stdio.h>
void main()
{
static int i;
for (;;)
if (i+++”Apple”)
printf(“Banana”);
else
break;
}
It is interpreted as i++ + "Apple". Since i is static and does not have an initializer, i++ yields 0. So the whole expression is 0 + some address or equivalent to if ("Apple").
EDIT
As Jonathan Leffler correctly notes in the comments, what I said above only applies to the first iteration. After that it will keep incrementing i and will keep printing "Banana".
I think at some point, due to overflows (if it doesn't crash) "Apple" + i will yield 0 and the loop will break. Again, I don't really know what a well-meaning compiler should do when one adds a pointer and a large number.
As Eric Postpischil commented, you can only advance the pointer until it points to one-past the allocated space. In your exxample adding 7 will advance the pointer one-past the allocated space ("Apples\0"). Adding more is undefined behavior and technically strange things can happen.
Use int main(void) instead of void main().
The expression i+++"Apple" is parsed as (i++) + "Apple"; the string literal "Apple" is converted from an expression of type "6-element array of char" to "pointer to char", and its value is the address of the first element of the array. The expression i++ evaluates to the current value of i, and as a side effect, the value in i is incremented by 1.
So, we're adding the result of the integer expression i++ to the pointer value resulting from the expression "Apple"; this gives us a new pointer value that's equal or greater than the address of "Apple". So assuming the address of the string literal "Apple" is 0x80123450, then basically we're evaluating the values
0x80123450 + 0
0x80123450 + 1
0x80123450 + 2
...
all of which should evaluate to non-zero, which causes the printf statement to be executed. The question is what happens when i++ results in an integer overflow (the behavior of which is not well defined) or the value of i+++"Apple" results in an overflow for a pointer value. It's not clear that i+++"Apple" will ever result in a 0-valued expression.
This code SHOULD Have been written like this:
char *apple = "Apple";
for(i = 0; apple[i++];)
printf("Banana");
Not only is it clearer than the code posted in the original, it is also clearer to see what it does. But I guess this came from "Look how bizarre we can write things in C". There are lots of things that are possible in C that isn't a great idea.
It is also possible to learn to balance a plate of hot food on your head for the purpose of serving yourself dinner. It doesn't make it a particularly great idea - unless you don't have hands and feet, I suppose... ;)
Edit: Except this is wrong... The equivalent is:
char *apple = "Apple";
for(i = 0; apple+i++ != NULL;)
printf("Banana");
On a 64-bit machine, that will take a while. If it finishes in reasonable time (sending output to /dev/null), I will update. It takes approximitely three minutes on my machine (AMD 3.4GHz Phenom II).

Copying a string in C

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

Resources