# Assigning a variable using a unary operator

• Comp Sci
Crystal037
Homework Statement:
I am using unary operator inside while loop to assign values, but it isn't doing doing anything
Relevant Equations:
None
C:
int a[]={12,34,55,76,89,23};
int n=5;
while(n>1){
a[n]=a[--n];}
for(int i=0;i<6;i++){
printf("%d\t",a[i]);
}
Mentor note: Please use code tags in future posts. I've added them to this code.
The above code should shift the element values to the right of each array cell, but after running the code it doesn't seem to be doing anything.

Last edited by a moderator:

Homework Helper
Gold Member
You need to decrement n after using it on the right-hand side of the assignment, not before.
Try replacing a[--n] by a[n--]

berkeman
Homework Helper
Gold Member
In line 15, when it assigns the value to the left side a[n] has the value of n already been decremented? If so, then it is the same as the right side a[n].
(I am not expert enough to know the answer, but I suspect this might be the problem.)

Crystal037
You need to decrement n after using it on the right-hand side of the assignment, not before.
Try replacing a[--n] by a[n--]
That wouldn't change anything right. The original values would be assigned back.

Crystal037
In line 15, when it assigns the value to the left side a[n] has the value of n already been decremented? If so, then it is the same as the right side a[n].
(I am not expert enough to know the answer, but I suspect this might be the problem.)
Nope I'm doing pre-increment using --n. What you r saying is post increment, that would be n--.

Homework Helper
Gold Member
Nope I'm doing pre-increment using --n. What you r saying is post increment, that would be n--.
I'm not convinced about that. If it is 'pre', then it has already been decreased on both sides of the equality before anything is done. If that is even done before the lvalue left-hand side is determined, then it is just putting the same value in the same spot.
Try assigning nOld = n before line 15 and changing line 15 to "a[nOld]=a[--n];". See if that makes a difference.
(PS. Those pre-increments and post-increments can be treacherous and some programming standards forbid their use. I would not use them unless there was a serious reason.)
(PPS. If you want to, you can examine the resulting assembler code of line 15 to see exactly what is happening and when.)

Homework Helper
2022 Award
It is stated here that
1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.
The following examples are given:
Code:
// For (1):
i = ++i + i++;

// For (2):
a[i] = i++;
f(i, i++);
These examples between them suggest that
Code:
a[i] = a[--i];
also produces undefined behaviour.

The fact that there is scope for debate about what that line of code does is reason enough to rewrite it; perhaps as
Code:
for(n = 5; n > 1; n--)
a[n] = a[n-1];

Grelbr42, hmmm27 and FactChecker
Homework Helper
Gold Member
It is stated here that

The following examples are given:
Code:
// For (1):
i = ++i + i++;

// For (2):
a[i] = i++;
f(i, i++);
These examples between them suggest that
Code:
a[i] = a[--i];
also produces undefined behaviour.
I think that another example in the reference makes an even better case. If something like this is undefined:
C:
i = i++ + 1; // undefined behavior
Then surely something like this is also undefined:
C:
a[n]=a[--n];
This being undefined may mean that it will give different results with different compilers -- a very bad thing.
The fact that there is scope for debate about what that line of code does is reason enough to rewrite it; perhaps as
Code:
for(n = 5; n > 1; n--)
a[n] = a[n-1];
Amen. The headaches of pre-increment and post-increment are just not worth it except for the very simplest cases where it is virtually the only thing being done.

Mentor
The above code should shift the element values to the right of each array cell
Your statement above is not clear in that it seems to imply that you are shifting the array values to the right. From your code, it appears that your goal is actually to shift each array value one position to the left.

As already noted in this thread, using increment or decrement operators can lead to undefined behavior in some cases, especially in assignment statements where the same variable appears on both sides of the assignment operator,

The following code moves each element one position to the left, with the old a[0] going into the bit bucket. Since each element has moved left by one position, when you print them out, the loop should run one less time.
C:
    int a[] = { 12, 34, 55, 76, 89, 23 };
int size = sizeof(a) / sizeof(int);
int temp;

for (int i = 0; i < size; i++) {
temp = a[i+1];
a[i] = temp;
}

Mentor
@Crystal037, I've noticed in several of your threads that, after some advice, you don't return. It would be nice, as well as good manners, if you acknowledged that advice, to say whether it helped or didn't.

Nobody gets paid here, so saying "thanks" goes a long way.

Crystal037
@Crystal037, I've noticed in several of your threads that, after some advice, you don't return. It would be nice, as well as good manners, if you acknowledged that advice, to say whether it helped or didn't.

Nobody gets paid here, so saying "thanks" goes a long way.
Oh I'm so sorry! Thank you all for answering my query. Now, I got to know about undefined behaviour of the code.

FactChecker and Mark44
valenumr
Late to the game, but per the standard post (in/de)crement operators return the altered value. Pre (in/de)crement operators may return the original value, but I don't think they have to return anything (thus undefined behavior in the standard). The optimizer can elect to use the pre increment operator when the altered value is not used.

Homework Helper
Gold Member
Late to the game, but per the standard post (in/de)crement operators return the altered value.
No you have this the wrong way round: prefix operators return (a reference to) the altered value, postifx operators return (a reference to a copy of) the value before alteration.

https://en.cppreference.com/w/cpp/language/operator_incdec

Pre (in/de)crement operators may return the original value, but I don't think they have to return anything
No, see above.

The optimizer can elect to use the pre increment operator when the altered value is not used.
The key point to remember is that with the right settings the optimizer is clever enough to produce exactly the same code for
C++:
accumulator += x[i];
i++; // Or ++i.
as
C++:
accumulator += x[i++];
so there is no point in doing the latter, follow the simple rule to never use the return value of an increment/decrement operator.

Some style guides go as far as to say don't use the increment/decrement operators at all - instead use
C++:
accumulator += x[i];
i += 1;
(and of course with the right optimizer settings for production code this will again compile to exactly the same object code).

DrClaude, valenumr and Grelbr42
valenumr
No you have this the wrong way round: prefix operators return (a reference to) the altered value, postifx operators return (a reference to a copy of) the value before alteration.

https://en.cppreference.com/w/cpp/language/operator_incdec

No, see above.

The key point to remember is that with the right settings the optimizer is clever enough to produce exactly the same code for
C++:
accumulator += x[i];
i++; // Or ++i.
as
C++:
accumulator += x[i++];
so there is no point in doing the latter, follow the simple rule to never use the return value of an increment/decrement operator.

Some style guides go as far as to say don't use the increment/decrement operators at all - instead use
C++:
accumulator += x[i];
i += 1;
(and of course with the right optimizer settings for production code this will again compile to exactly the same object code).
You are correct.

Homework Helper
Gold Member
There are other problems that I don't think have been mentioned with using the postfix operator this way: a = 2 + x[i++];
1) Suppose you want to modify the code so that there is something between the assignment to a and the index increment. This code makes it harder to make that change without unnecessarily changing this line.
2) It is also harder to spot that the index has been incremented on this line and is easy to overlook.
3) It makes the documentation of that line messy.
4) Some coding standards forbid side effects. I consider the index increment to be a side effect.

valenumr
Mentor
2) It is also harder to spot that the index has been incremented on this line and is easy to overlook.
I agree that it is easy to overlook, but experienced C/C++ programmers will know that in the example you showed, the index doesn't get incremented until the next line; i.e., after the sequence point signified by the terminating semicolon (;) has been passed. A sequence point is a place in a program at which it is guaranteed that all side effects of previous operations have been performed. See https://en.wikipedia.org/wiki/Sequence_point.

In this example code, a = 2 + x[i++];, if the value of i is 2, array element x[2] is evaluated and then added to 2. This sum is then assigned to a. In the next line i's new value will be 3.

4) Some coding standards forbid side effects. I consider the index increment to be a side effect.
The increment and decrement operators cause side effects but aren't themselves side effects. The side effect in this case is that the index variable gets changed.

Homework Helper
Gold Member
I agree that it is easy to overlook, but experienced C/C++ programmers will know that in the example you showed, the index doesn't get incremented until the next line; i.e., after the sequence point signified by the terminating semicolon (;) has been passed. A sequence point is a place in a program at which it is guaranteed that all side effects of previous operations have been performed. See https://en.wikipedia.org/wiki/Sequence_point.
Yes, good point. I wrestled with whether to use a simple example or a complicated example. Of course, this and other examples are so simple that I have used such simple code many times. I have made hundreds of lines in a row that increment the index, especially when packing or unpacking a structure. Those are easy to understand and have very little likelihood of causing a problem.
So I would recommend anyone reading my post to imagine a more complicated example, where the likelihood of a problem can be much more significant.
In this example code, a = 2 + x[i++];, if the value of i is 2, array element x[2] is evaluated and then added to 2. This sum is then assigned to a. In the next line i's new value will be 3.
Yes. I understand and I hope that others do too.
The increment and decrement operators cause side effects but aren't themselves side effects. The side effect in this case is that the index variable gets changed.
Yes, it is code that causes a side effect. I fail to see a significant problem with how I used the phrase and I think that the wording can be forgiven.

Mentor
Yes, it is code that causes a side effect. I fail to see a significant problem with how I used the phrase and I think that the wording can be forgiven.
I was just trying to be more precise in the wording.

FactChecker