I'm having trouble wrapping my head around a concept in C regarding the use of the operator ++ and arrays. I know enough that ++ will increment a value, but I'm running into a code snippet that does not make any sense to me:
while((c = getchar()) != EOF)
{
if(c < NUM_CHARS)
{
thisval = ++freqarr[c];
if(thisval > maxval)
{
maxval = thisval;
}
}
the line thisval = ++freqarr[c]; does not make a lot of sense to me.
Does it mean that thisval adds an additional index or value to the array?
I'm still new to C, so I'm not sure if this is common in C or not, if it's not or looked down upon, please let me know.
Prefix ++ has lower precendence than [], see https://en.cppreference.com/w/c/language/operator_precedence. So this is equivalent to thisval = ++(freqarr[c]);. It takes the cth element of the array, and increments that element, then assigns the new value to thisval. Just like:
freqarray[c] = freqarray[c] + 1;
thisval = freqarray[c];
I presume that c is defined as an int and freqarr is defined as an array. (It's generally best to include a Minimal, Reproducible Example in your question).
The prefix ++ operator increments an object and yields the incremented value. freqarr[c] is an object. The fact that it happens to be an element of an array is not relevant here. It works the same way as it would if it were applied to a simple named variable.
Note that the indexing operator [] binds more tightly than ++, so the expression ++freqarr[c] is equivalent to ++(freqarr[c]).
The prefix ++ operator increments its operand, and the resulting expression has the incremented value.
So this line does two things:
It increments the value of freqarr[c] which is a member of an array
It assigned the incremented value of freqarr[c] to thisval
Related
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.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 9 years ago.
I am solving a problem that reads a set of text lines and prints the longest.
The problem is from K&R "The C programming language" section 1.9. The book provides a solution but I tried to solve it in my own way. The code below works but before I get it to work, I was getting a problem due to the line longestStr[i++] = tmpStr[j++] as I have previously used longestStr[i++] = tmpStr[i++] thinking that i would be incremented once the assignment was done. But that was not the case. Is this how postfix operator normally works?
#include <stdio.h>
#define MAXLINE 100
main()
{
int lineLength = 0, longestLine = 0;
int c, i, j;
char longestStr[MAXLINE];
char tmpStr[MAXLINE];
while((c = getchar()) != EOF)
{
tmpStr[lineLength++] = c;
if(c == '\n')
{
if( lineLength > longestLine)
{
longestLine = lineLength;
i = 0, j = 0;
while(i < lineLength)
{
longestStr[i++] = tmpStr[j++]; // I tried longestStr[i++] = tmpStr[i++] but it gives wrong result
}
}
lineLength = 0;
}
}
printf("Longest line is - %d long\n", longestLine-1);
for(i = 0; i < longestLine-1; i++)
printf("%c", longestStr[i]);
putchar('\n');
}
The postfix increments or decrements are operators that perform the increment or decrement after the use of the variable, such that if you wish to use a integer value to print out and add it at the same time you would use postfix.
int i = 0;
printf("%d",i++);
//prints out 0
Prefix increment/decrement however works in the opposite manner such that it performs the increment/decrement prior to the use of the variable, such that if you wish to increment/decrement a variable before printing it out, you would use prefix
int i = 0;
printf("%d",++i);
//prints out 1
The problem you have is not related to how the postfix operator works, but rather to what you intend to do in the code line which gives you a problem.
As asked in the comments, what is the meaning of the line as you wrote it initially?
longestStr[i++] = tmpStr[i++];
Because the C standard does not specify it, this line can be interpreted in several ways:
longestStr[i] = tmpStr[i+1];
i += 2;
or
longestStr[i+1] = tmpStr[i];
i += 2;
or
longestStr[i] = tmpStr[i];
i += 2;
In every case, you end up with a counter incremented twice, which will mess up your algorithm.
The correct way is to increment the counter in a separate line, or use the working solution (you are providing), which should be compiled down to the same code with any decent compiler.
Note that you should probably check for the counter not going beyond the maximum allowed line size MAXLINE (unless the problem states that this cannot happen with the input, but even in that case, it would be helpful for situations like yours, where the code wrongly increment the counter twice).
try to understand how post fix increment works.
f(i++) is equivalent to the operation 'call f on the current value of i, then increment i'
For example, when you use i++ twice, and initial value of i = 1, a(i++) = b(i++) means, a(1)=b(2) and the value of i after the operation is i=3.
If you want to eliminate one variable in what you are trying to do, you have to make sure you use increment only once. Do it like, a(i)=(b(i); i++
Whereas the postfix increment operator evaluates the original value, it is understandable to think the actual incrementating doesn't happen until sometime down the road. However this is not the case. You should conceptualize postfix as if the incrementing is happening while the original value is being returned.
The bigger issue though is that your statement increments i twice. This means i will increase by two with each iteration of your loop. Futhermore your index values will be off by one from each other, That's because if a variable changes during one part of statement evaluation, those changes become instantly visible to parts of the statement which have not yet evaluated.
I'm just learning some C, or rather, getting a sense of some of the arcane details. And I was using VTC advanced C programming in which I found that the sequence points are :
Semicolon
Comma
Logical OR / AND
Ternary operator
Function calls (Any expression used as an argument to a function call is finalized the call is made)
are all these correct ?. Regarding the last one I tried:
void foo (int bar) { printf("I received %d\n", bar); }
int main(void)
{
int i = 0;
foo(i++);
return 0;
}
And it didnt print 1, which according to what the VTC's guy said and if I undertood correctly, it should, right ?. Also, are these parens in the function call the same as the grouping parens ? (I mean, their precedence). Maybe it is because parens have higher precedence than ++ but I've also tried foo((i++)); and got the same result. Only doing foo(i = i + 1); yielded 1.
Thank you in advance. Please consider that I'm from South America so if I wasnt clear or nothing makes sense please, oh please, tell me.
Warmest regards,
Sebastian.
Your code is working like it should and it has nothing to do with sequence points. The point is that the postfix ++ operator returns the non-incremented value (but increments the variable by 1 nonetheless).
Basically:
i++ – Increment i by one and return the previous value
++i – Increment i by one and return the value after the increment
The position of the operator gives a slight hint for its semantics.
Sequence means i++ is evaluted before foo is invoked.
Consider this case (I am not printing bar!):
int i = 0;
void foo (int bar) { printf("i = %d\n", i); }
int main(void){
foo(i++);
return 0;
}
i = 1 must be printed.
C implements pass-by-value semantics. First i ++ is evaluated, and the value is kept, then i is modified (this may happen any time between the evaluation and the next sequence point), then the function is entered with the backup value as the argument.
The value passed into a function is always the same as the one you would see if using the argument expression in any other way. Other behavior would be fairly surprising, and make it difficult to refactor common subexpressions into functions.
When you do something like:
int i = 0, j;
j = i++;
the value of i is used first and then incremented. hence in your case the values of i which is 0 is used (hence passed to your function foo) and then incremented. the incremented values of i (now 1) will be available only for main as it is its local variable.
If you want to print 1 the do call foo this way:
foo(++i);
this will print 1. Rest you know, why!
#include <stdio.h>
main()
{
int i;
for(i=0; i<0, 5; i++)
printf("%d\n", i);
}
I am unable to understand the i<0, 5 part in the condition of the for loop.
Even if I make it i>0, 5, there's no change in output.
How does this work?
On topic
The comma operator will always yield the last value in the comma separated list.
Basically it's a binary operator that evaluates the left hand value but discards it, then evaluates the right hand value and returns it.
If you chain multiple of these they will eventually yield the last value in the chain.
As per anatolyg's comment, this is useful if you want to evaluate the left hand value before the right hand value (if the left hand evaluation has a desirable side effect).
For example i < (x++, x/2) would be a sane way to use that operator because you're affecting the right hand value with the repercussions of the left hand value evaluation.
http://en.wikipedia.org/wiki/Comma_operator
Sidenote: did you ever hear of this curious operator?
int x = 100;
while(x --> 0) {
// do stuff with x
}
It's just another way of writing x-- > 0.
Comma operator evaluates i<0 Or i>0 and ignores. Hence, it's always the 5 that's present in the condition.
So it's equivalent to:
for(i=0;5;i++)
The coma operator is done to the initialization and to the increment part, to do something like for(i=0,j=20;i<j;i++,j--), if you do it in the comparation part it will evaluate the last one (as it was already answered before)
i<0,5 will always evaluate to 5, as always the right expression will be returned for ex1,ex2 .
The comma operator is intended for cases where the first operand has some side effects. It's just an idiom, meant to make your code more readable. It has no effect on the evaluation of the conditional.
For example,
for (i = 0; i<(i++, 5); i++) {
// something
}
will increment i, and then check if i<5.
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).