Assigning a variable using a unary operator

  • Comp Sci
  • Thread starter Crystal037
  • Start date
  • #1
Crystal037
165
7
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.
Screenshot (147).png
Screenshot (147).png
 
Last edited by a moderator:

Answers and Replies

  • #2
andrewkirk
Science Advisor
Homework Helper
Insights Author
Gold Member
4,066
1,645
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--]
 
  • #3
FactChecker
Science Advisor
Homework Helper
Gold Member
7,737
3,399
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.)
 
  • #4
Crystal037
165
7
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.
 
  • #5
Crystal037
165
7
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--.
 
  • #6
FactChecker
Science Advisor
Homework Helper
Gold Member
7,737
3,399
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.)
 
  • #7
pasmith
Homework Helper
2022 Award
2,592
1,196
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];
 
  • Like
Likes Grelbr42, hmmm27 and FactChecker
  • #8
FactChecker
Science Advisor
Homework Helper
Gold Member
7,737
3,399
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.
 
  • #9
36,883
8,935
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;
    }
 
  • #10
36,883
8,935
@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.
 
  • #11
Crystal037
165
7
@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.
 
  • Like
Likes FactChecker and Mark44
  • #12
valenumr
467
191
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.
 
  • #13
pbuk
Science Advisor
Homework Helper
Gold Member
4,084
2,411
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).
 
  • Like
Likes DrClaude, valenumr and Grelbr42
  • #14
valenumr
467
191
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.
 
  • #15
FactChecker
Science Advisor
Homework Helper
Gold Member
7,737
3,399
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.
 
  • #16
36,883
8,935
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.
 
  • #17
FactChecker
Science Advisor
Homework Helper
Gold Member
7,737
3,399
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.
 
  • #18
36,883
8,935
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.
 
  • Like
Likes FactChecker

Suggested for: Assigning a variable using a unary operator

  • Last Post
Replies
1
Views
347
Replies
2
Views
407
Replies
42
Views
682
  • Last Post
Replies
1
Views
1K
Replies
2
Views
618
Replies
6
Views
121
Replies
10
Views
479
Replies
1
Views
326
Replies
2
Views
302
Replies
7
Views
726
Top