#include <iostream>
using namespace std;
int main()
{
int arr[8];
int n = 0;
while (n < 8)
{
arr[n] = n;
}
for (n = 0; n < 8; n )
{
cout << arr[n]<<" ";
}
}
output- garbage 1 2 3 4 5 6 7 expected output- 1 2 3 4 5 6 7 8
CodePudding user response:
The statement arr[n] = n;
has Undefined Behavior because it is unspecified if n
is incremented before being used as the subscript in arr
.
In your case, with your compiler, the increment happens first, so that you never assign anything to arr[0]
and write past the end arr[8]
of the array.
One way to address this is to split it into two statements:
arr[n] = n;
n;
The evaluation order is known as sequencing, and the rules have changed as the language has evolved. Of significance, with C 17 the increment of n
will happen before calculating the address to store the result in, so you'll always end up with an uninitalized first element and the write past the end of the array.
CodePudding user response:
Turn on your warning flags! Your program can have undefined behavior;
main.cpp:34:18: warning: operation on 'n' may be undefined [-Wsequence-point]
34 | arr[n] = n;
| ^~~
main.cpp:34:16: warning: iteration 7 invokes undefined behavior [-Waggressive-loop-optimizations]
34 | arr[n] = n;
| ~~~~~~~^~~~~
main.cpp:32:14: note: within this loop
32 | while (n < 8)
Maybe you could do this instead:
int arr[8] { };
int n = 0;
while ( n < 8 )
{
arr[n] = n 1;
n;
}
for ( n = 0; n < 8; n )
{
std::cout << arr[n] << " ";
}
CodePudding user response:
In C the expression on the right hand side (RHS) of the =
sign is evaluated first, because you can't store (assign) a value in a variable if you haven't calculated what it is!
int myAge = 10 10; // calculates 20 first, then stores it.
You're changing the value of n before assigning to position n in your array - increasing it from 0 to 1 in the first iteration of the loop - and so assigning the result, 1, to array[1].
Why? Well, n
and n
are complicated (and frequently confusing) operators in c , in that that they're both mathematical and assignment operators. n is essentially equivalent to:
n = n 1;
return n;
Where n is closer to:
n = n 1;
return n -1;
You can code it more explicitly with simpler operators:
arr[n] = n 1;
n = n 1;
.. or use a for loop as you did in your output code. Using the same looping structures for both might help you achieve consistent outcomes.
You're not alone in struggling with this one. Chris Lattner felt the
and --
unary operators' potential for obfuscation and bugs sufficiently outweighed their benefits that they were dropped from Swift 3.