So i have this main:
#define NUM 5
int main()
{
int a[NUM]={20,-90,450,-37,87};
int *p;
for (p=a; (char *)p < ((char *)a + sizeof(int) * NUM); ) //same meaning: for (p=a; p<a+NUM;)
*p++ = ++*p < 60 ? *p : 0; //same meaning: *(p++)=++(*p)<60?*p:0;
for(p=a; (char *)p < ((char *)a + sizeof(int) * NUM); )
printf("\n %d ", *p++);
return 0;
}
And i need to find what is the output.
So after try to understand without any idea i run it and this is the output:
21
-89
0
-36
0
So i will glad to explanation how to solve this kind of questions (i have exam soon and this type of questions probably i will see..)
EDIT:
at the beginning i want to understand what the first forstatement doing:
This jump 1 integer ? and what this going inside the block ?
And what is the different between *p++ and ++*p
The question is similar to Why are these constructs (using ++) undefined behavior in C? although not an exact duplicate due to the (subtle) sequence point inside the ?: operator.
There is no predictable output since the program contains undefined behavior.
While the sub-expression ++*p is sequenced in a well-defined way compared to *p because of the internal sequence point of the ?: operator, this is not true for the other combinations of sub-expressions. Most notably, the order of evaluation of the operands to = is not specified:
C11 6.5.15/3:
The evaluations of the operands are unsequenced.
*p++ is not sequenced in relation to ++*p. The order of evaluation of the sub-expressions is unspecified, and since there are multiple unsequenced side-effects on the same variable, the behavior is undefined.
Similarly, *p++ is not sequenced in relation to *p. This also leads to undefined behavior.
Summary: the code is broken and full of bugs. Anything can happen. Whoever gave you the assignment is incompetent.
at the beginning i want to understand what the first for statement doing
This is what one would call code obfuscation... The difficult part is obviously this one:
(char *)p < ((char *)a+sizeof(int)*NUM);
OK, we convert p to a pointer to char, then compare it to another pointer retrieved from array a that points to the first element past a: sizeof(int)*NUM is the size of the array - which we could have gotten much more easily by just having sizeof(a), so (char*)p < (char*)a + sizeof(a)
Be aware that comparing pointers other than with (in-)equality is undefined behaviour if the pointers do not point into the same array or one past the end of the latter (they do, in this example, though).
Typically, one would have this comparison as p < a + sizeof(a)/sizeof(*a) (or sizeof(a)/sizeof(a[0]), if you prefer).
*p++ increments the pointer and dereferences it afterwards, it is short for p = p + 1; *p = .... ++*p, on the other hand first dereferences the pointer and increments the value it is pointing to (note the difference to *++p, yet another variant - can you get it yourself?), i. e. it is equivalent to *p = *p + 1.
The entire line *p++ = ++*p<60 ? *p : 0; then shall do the following:
increment the value of *p
if the result is less than 60, use it, otherwise use 0
assign this to *p
increment p
However, this is undefined behaviour as there is no sequence point in between read and write access of p; you do not know if the left or the right side of the assignment is evaluated first, in the former case we would assign a[i] = ++a[i + 1], in the latter case, a[i] = ++a[i]! You might have gotten different output with another compiler!!!
However, these are only the two most likely outputs – actually, if falling into undefined behaviour, anything might happen, the compiler might just to ignore the piece of code in question, decide not to do anything at all (just exit from main right as the first instruction), the program might crash or it could even switch off the sun...
Be aware that one single location with undefined behaviour results in the whole program itself having undefined behaviour!
Short answer: because of this line
*p++ = ++*p<60 ? *p : 0;
it is impossible to say how the program behaves. When we access *p on the right-hand side, does it use the old or the new value of p, that is, before or after the p++ on the left-hand side gets to it? There is no rule in C to tell us. What there is instead is a rule that says that for this reason the code is undefined.
Unfortunately the person setting the question didn't understand this, thinks that "tricky" code line this is something to make a puzzle about, instead of something to be avoided at all costs.
The only way to really understand this kind of stuff (memory management, pointer behaviour, etc.) is to experiment yourself. Anyway, I smell someone is trying to seem clever fooling students, so I will try to clarify a few things.
int a[NUM]={20,-90,450,-37,87};
int *p;
This structure in memory would be something like:
This creates a vector of five int, so far, so good. The obvious move, given that data, is to run over the elements of a using p. You would do the following:
for(p = a; p < (a + NUM); ++p) {
printf("%d ", *p);
}
However, the first change to notice is that both loops convert the pointers to char. So, they would be:
for (p=a;(char *)p<((char *)a+sizeof(int)*NUM); ++p) {
printf("%d ", *p);
}
Instead of pointing to a with a pointer to int the code converts pto a pointer to char. Say your machine is a 32bit one. Then an int will probably occupy four bytes. With p being a pointer to int, when you do ++p then you effectively go to the next element in a, since transparently your compiler will jump four bytes. If you convert the int pointer to a char instead, then you cannot add NUM and assume that you are the end of the array anymore: a char is stored in one byte, so ((char *)p) + 5 will point to the second byte in the second element of a, provided it was pointing at the beginning of a before. That is way you have to call sizeof(int) and multiply it by NUM, in order to get the end of the array.
And finally, the infamous *p++ = ++*p<60 ? *p : 0;. This is something unfair to face students with, since as others have already pointed out, the behaviour of that code is undefined. Lets go expression by expression.
++*p means "access p and add 1 to the result. If p is pointing to the first position of a, then the result would be 21. ++*pnot only returns 21, but also stored 21 in memory in the place where you had 20. If you were only to return 21, you would write; *p + 1.
++*p<60 ? *p : 0 means "if the result of permanently adding 1 to the value pointed by p is less than 60, then return that result, otherwise return 0.
*p++ = x means "store the value of x in the memory address pointed by p, and then increment p. That's why you don't find ++p or p++ in the increment part of the for loop.
Now about the whole instruction (*p++ = ++*p<60 ? *p : 0;), it is undefined behaviour (check #Lundin's answer for more details). In summary, the most obvious problem is that you don't know which part (the left or the right one), around the assignment operator, is going to be evaluated first. You don't even know how the subexpressions in the expression at the right of the assignment operator are going to be evaluated (which order).
How could you fix this? It would be actually be very simple:
for (p=a;(char *)p<((char *)a+sizeof(int)*NUM); ++p) {
*p = (*p + 1) <60 ? (*p + 1) : 0;
}
And much more readable. Even better:
for (p = a; p < (a + NUM); ++p) {
*p = (*p + 1) <60 ? (*p + 1) : 0;
}
Hope this helps.
Related
I'm new in C, stuck in understanding the expression s[i ++] = t[j ++], I don't know how it's possible that an array element gets accessed with a variable and then the variable increase itself and then the array element just accessed is again accessed with the original variable and then gets assigned to another array's element, I'm confused, I think to understand the exact process might involve some low-level knowledges, but I don't want to digress too far away, is there any way to understand it easily and clearly?
In C language, the expression i++ causes i to be incremented, but the expression i++ itself evaluates to the value i had before being incremented. So the expression s[i++] = t[j++] has the same behaviour as:
s[i] = t[j];
i = i + 1;
j = j + 1;
except that the precise order is not specified. For that last reason, the rule is that a variable should only be modified once: s[i++] = t[i++] would invoke Undefined Behaviour.
Like any other complicated-looking expression, it's easier to understand this if you break it down into parts.
The key is that innermost part (or "subexpression") i++. I assume you know what i++ does by itself, although in this example, we're hopefully going to get a deeper appreciation of what i++ is actually good for. Why would you want to "increment i, but return the old value"? What's the use of this? Well, the main use is that it's super useful for moving along an array.
Lets look at a simpler example. Suppose we have an array a that we want to store some numbers in. The most basic way is
int a[10];
a[0] = 12;
a[1] = 34;
a[2] = 5678;
Another very good way is to use a second variable like i to keep track of where we're storing:
i = 0;
a[i] = 12;
i = i + 1;
a[i] = 34;
i = i + 1;
a[i] = 5678;
i = i + 1;
I've written this out in "longhand", but of course in C, you would almost never write it this way, because the "C way" is the much more concise
i = 0;
a[i++] = 12;
a[i++] = 34;
a[i++] = 5678;
So first, make sure you understand that the "shorthand" and "longhand" forms work exactly the same way. Make sure you understand that when we say something like
a[i++] = 34;
what this means is "store 34 into the slot in array a indicated by i, and then update i to be one more than is used to be, so that it indicates the next slot."
In other words, we use an expression like a[i++] whenever we want to move along an array and do something with its elements, one by one, in order.
So far we were storing values into the array, but the idiom works just as well for fetching values out of an array. For example, this code prints those three elements, again one at a time, in order:
i = 0;
printf("%d\n", a[i++]);
printf("%d\n", a[i++]);
printf("%d\n", a[i++]);
My point is, again, that any time you see an expression like a[i++], you should think "we're moving along the array".
So now, finally, we can look at the expression you initially asked about:
s[i++] = t[j++];
Here we have two instances of the idiom. We're using i to move along the array s, and we're using j to move along the array t. We're fetching from t as we move along, and we're storing the values into s.
I don't know whether s and t are arrays of characters, or integers, or what. Also I don't know that s and t are truly arrays -- they might actually be pointers, pointing into some arrays. But I don't really have to know those things to know that the essential meaning of s[i++] = t[j++] is "copy elements from array t to array s, using j to keep where we are in t, and i to keep track of where we are in s".
[The above is an answer to your original question. The rest of this answer isn't directly related, but is essential to avoid inadvertently writing incorrect programs using ++ and --.]
As I said, the subexpression i++ and the idiom a[i++] are super useful for moving through arrays. But there are a couple things to beware of. (Actually it's just one thing, but it crops up in lots of different ways.)
Earlier I wrote the code
i = 0;
printf("%d\n", a[i++]);
printf("%d\n", a[i++]);
printf("%d\n", a[i++]);
to print the first three elements of the array a. But it prints them as bare, isolated numbers. What if I want to always see which array index each number comes from? That is, what if I'm tempted to write something like this:
i = 0;
printf("%d: %d\n", i, a[i++]); /* WRONG */
printf("%d: %d\n", i, a[i++]); /* WRONG */
printf("%d: %d\n", i, a[i++]); /* WRONG */
If I wrote this, my intent would be that I would see the obvious display
0: 12
1: 34
2: 56788
But when I actually tried it just now, I got this instead:
1: 12
2: 34
3: 5678
The numbers 12 and 34 and 5678 are right, but the indices 1, 2, and 3 are all wrong -- they're off by one! How did that happen?
And the answer is that although i++ is, as I said, "super useful", it turns out that there's a fine line between "super useful" and what's called undefined behavior.
That printf call
printf("%d: %d\n", i, a[i++]); /* WRONG */
looks fine, but it's not actually well-defined, because the compiler does not necessarily evaluate everything left-to-right, so it's not actually guaranteed that it will use the old value of i for the %d: part. The compiler might evaluate things from right to left, meaning that a[i++] will happen first, meaning that %d: will print the new value, instead -- which appears to be what happened when I tried it.
Here's another potential issue. Your original question was about
s[i++] = t[j++];
which, as we've seen, copies elements from t to s based on two possibly-different indices i and j. But what if we know we always want to copy t[1] to s[1], t[2] to s[2], t[3] to s[3], etc.? That is, what if we know that i and j will always be the same, so we don't even need separate i and j variables? How would we write that? Our first try might be
s[i++] = t[i++]; /* WRONG */
but that can't be right, because now we're incrementing i twice, and we'll probably do something totally broken like copying t[1] to s[2] and t[3] to s[4]. But if we want to only increment i once, should it be
s[i++] = t[i]; /* WRONG */
or
s[i] = t[i++]; /* WRONG */
But the answer is that neither of these will work. In expressions like these, which have i in one place and i++ in the other place, there's no way to tell whether i gets the old value or the new value. (In particular, there's no left-to-right or right-to-left rule that would tell us.)
So although expressions like i++ and a[i++] are indeed super useful, you have to be careful when you use them, to make sure you don't go over the edge and have too much happening at once, such that the evaluation order becomes undefined. Sometimes this means you have to back off, and not use the "super useful" idiom, after all. For example, a safe way to print those values would be
printf("%d: %d\n", i, a[i]); i++;
printf("%d: %d\n", i, a[i]); i++;
printf("%d: %d\n", i, a[i]); i++;
and a safe way to copy from t[1] to s[i] would be
s[i] = t[i]; i++;
You can read more in this answer about how to recognize well-defined expressions involving ++ and --, and how to avoid the undefined ones.
The evaluations of s[i++] and t[j++] are unsequenced relative to each other. Semantically, it's equivalent to:
t1 = i;
t2 = j;
s[t1] = t[t2];
i = i + 1;
j = j + 1;
with the caveat that the last three assignments can happen in any order, even simultaneously (either in parallel or interleaved)1. The compiler doesn't have to create temporaries, either - the whole thing can be evaluated as
s[i] = t[j];
i = i + 1;
j = j + 1;
Alternately, the side effects of i++ and j++ can be applied before the update to s:
t1 = j;
j = j + 1;
t2 = i;
i = i + 1;
s[t2] = t[t1];
The current values of i and j must be known before you can index into the arrays, and the value of t[j] must be known before it can be assigned to s[i], but beyond that there's no fixed order of evaluation or of the application of side effects.
This is why expressions like x = x++ or a = b++ * b++ or a[i] = i++ all invoke undefined behavior - there's no fixed order for evaluating or applying side effects, so the results can vary by compiler, compiler settings, even by the surrounding code, and the results don't have to be consistent from run to run.
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.
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).
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).