This 'for' loop prints '1' instead of an array value - c++

Why does this...
int a[5];
a[-2] = 1;
a[-1] = 2;
a[0] = 3;
a[1] = 4;
a[2] = 5;
cout << a[-2] << endl <<endl;
for(int i=-2 ; i<=2 ; i++)
{
cout << a[i] << endl;
}
...output this?
1
-2
2
3
4
5
I created another project file in Code::Blocks, compiled, and got this:
1
1
-1
3
4
5
I tried to find posts with similar problems, but I couldn’t find any. This just doesn’t make sense to me.

Accessing arrays in C++ using negative indices is undefined behavior, the valid index for:
int a[5];
will be 0 to 4.
If we look at the draft C++ standard section 8.3.4 Arrays in paragraph 1 says:
[...] If the value of the constant expression is N, the array has N elements numbered 0 to N-1, [...]

Your code exhibits undefined behavior: -2 is not a valid index into int[5] array. Valid indexes into such array are 0 through 4.
In this particular case, it just so happens, by accident, that i is located in memory at exactly the offset 2 * sizeof(int) below the first element of a, so a[-2] happens to be an alias for i.

Related

Why am i getting the garbage value at index 0

#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
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.
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] << " ";
}
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.

Why are variable length arrays in C++ overlapping on some sizes?

After providing an answer to a question here, I was testing this code that I edited and noticed some strange behavior:
#include <iostream>
#define MAX 100
using namespace std;
int main()
{
int size = 0;
int array[MAX];
int i, j;
int input;
cout << "Array: ";
for(i = 0; i < MAX; i++)
{
cin >> input;
if(input == -1)
break;
else
{
array[i] = input;
size++;
}
}
cout << "Size: " << size << "\n\n";
int left[size / 2];
int right[size / 2];
for(i = 0; i < size / 2; i++)
left[i] = array[i];
for(i = size / 2, j = 0; i < size; i++, j++)
right[j] = array[i];
cout << "Left: ";
for(i = 0; i < size / 2; i++)
cout << left[i] << ' ';
cout << '\n';
cout << "Right: ";
for(i = 0; i < size - size / 2; i++)
cout << right[i] << ' ';
cout << '\n';
return 0;
}
This code is supposed to split the array into two separate arrays. Somehow the output is wrong when these are the input:
1 2 3 4 5 6 7 8 9 -1
Left: 9 2 3 4
Right: 5 6 7 8 9
After debugging If the elements of left were printed like this:
for(i = size / 2, j = 0; i < size; i++, j++)
{
right[j] = array[i];
cout << left[0] << ' ';
}
cout << '\n';
It says that the value of left[0] is modified after the 5th iteration:
1 1 1 1 9
Left: 9 2 3 4
Right: 5 6 7 8 9
This only happens when the array size is 9. I haven't tested beyond 16 yet. I could fix the code so that it would have the correct size
int right[size - size / 2];
or use malloc() to adhere to the C++ Standard,
int *left = (int *) malloc(sizeof(*left) * n / 2);
int *right = (int *) malloc(sizeof(*left) * n / 2);
so that left wouldn't be affected, but that's not what I'm asking. Why does it only happen when splitting an array size of 9? Why was left[0] overwritten? Is this is a bug in g++ that should be reported or is the problem something else?
It says that the value of left[0] is modified after the 5th iteration:
That is your answer. The problem occurs in the fifth iteration over an array with four elements.
When size is odd, the calculation of size/2 rounds down. So the sum size/2 + size/2 is strictly less than size, yet your loops ensure that all size elements from the original array are assigned somewhere. Something has to be assigned to an unexpected location. We call this "undefined behavior", and whatever the compiler does at that point is correct according to the C++ standard. (Whatever happens, the compiler gets to blame your code for it.) It just happens that when size is 9, the compiler used left[0] as the location for right[4].
Behind the scenes, the left and right arrays are probably more-or-less adjacent in memory. The layout would have right[0] through right[size/2], then possibly some unused space (also known as "padding"), then left[0] through left[size/2]. When you access one-past the last element of right, you end up either in the unused space or in left[0]. When you overwrite the unused space, you see no symptoms since that space is otherwise unused. However, when you overwrite left[0] you definitely see a symptom.
Your compiler apparently uses padding to make sure the arrays are aligned to 4*sizeof(int). (Must be faster that way, as compilers rarely introduce waste without a reason. Still, I am surprised it's not 2*sizeof(int) instead.) That is, there is no padding when size/2 is a multiple of 4. If this guesswork is accurate, you should see this behavior when size is odd and size/2 is a multiple of 4; that is when size is one more than a multiple of 8, as in 9, 17, 25, 33, etc.

Why the 2-D array prints 1 where it should not?

My code prints 1 at every position except the first column. I want it to print 1 at certain specific places (r, c) where r is the row and c is the column. Also, can anybody tell me how do I initialize the 2-D array with 0 at every index?
I have tried to reset the values of r and c to zero but nothing changes.
int main()
{
int T;
cin>>T;
while(T--)
{
vector <long long int>R;
vector <long long int>C;
long long int N, M, K, r, c, i, j, k; // N -> rows, M -> columns
cin>>N>>M>>K;
long long int arr[N][M];
cout<<K<<endl;
for(i=0; i<N; i++)
{
for(j=0; j<M; j++)
{
arr[i][j] = 0;
}
}
for(k=0; k<K; k++)
{
cin>>r>>c;
arr[r][c] = 2;
r = 0; c = 0;
}
for(i=0; i<N; i++)
{
for(j=0; j<M; j++)
{
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
}
return 0;
}
Input:
1 4 4 9 1 4 2 1 2 2 2 3 3 1 3 3 4 1 4 2 4 3
Some remarks:
Firstly, C-Style Array sizes must be known at compile time for standard C++, so you can't read them from cin (this is a GCC extension).
So if you need an array with a size known only at runtime, I suggest std::vector.
Additionally, in C++ it is common practice to define the loop variable inside the scope of the for-loop, like so:
for (int i = 0; i < N ++i)
This keeps the surrounding scope cleaner. An array or struct can be initialized to zero in C++ with the following uniform initialization syntax:
SomeStruct x{}; // All members are default initialized (e. g. for built-in types: 0)
SomeType myArray[N][M]{}; // All elements are default initialized
A comment like this
// N -> rows, M -> columns
is really just saying you should be naming your variables rows/cols and not N/M. Make your code self-documenting ;)
I would not recommend using std::endl when you want a line-break, as it also flushes the buffer, which when writing to files could
have serious performance implications (for console output it's no problem). It is better practice to use '\n' for line-breaks and use std::flush explicitly if you need it.
I've omitted the outer while loop and made Rows/Columns constant for simplicity. With std::vector you should use Rows*Cols as size in a
1D array and then map a position (i,j) to the 1D index with the formula:
arr2D[i][j] = arr1D[i*Cols + j];
If you choose to let the user specify rows/cols and use
std::vector<int> vec(rows*cols);
As your array.
int main()
{
constexpr int rows{3};
constexpr int cols{3};
int numUserValues{};
cin >> numUserValues;
int arr[rows][cols]{};
cout << numUserValues << '\n';
for(int k=0; k<numUserValues; k++)
{
int r{};
int c{};
if (cin>>r>>c && r>=0 && r<rows && c>=0 && c<cols) {
arr[r][c] = 2;
}
}
for(int i=0; i<N; i++)
{
for(int j=0; j<M; j++)
{
cout<<arr[i][j]<<" ";
}
cout<<'\n';
}
return 0;
}
Your program is very user-unfriendly, since you have no prompts at all (e.g. cout << "Enter number of rows: ";, but this is my test-run, as you can see all elements are zero except for the ones I specified:
$ ./test
5
5
0 0
1 1
2 2
0 1
0 2
2 2 2
0 2 0
0 0 2
Your question is hard to answer, because you say "I want to print 1 at position ...", while your code says arr[r][c] = 2; ;)
"My code prints 1 at every position except first column", would mean for a 5x5:
0 1 1 1 1
0 1 1 1 1
0 1 1 1 1
0 1 1 1 1
0 1 1 1 1
Which is simply not the case and thus false information.
I want it to print 1 at certain specific places (r, c) where r is the row and c is the column
You are doing this:
cin>>r>>c;
arr[r][c] = 2;
when the input is "1 4", which invokes Undefined Behavior (UB), because you go out of range, since the 2D array you have is of 4x4 dimensions, thus you would need to do something like this instead:
arr[r - 1][c - 1] = 1;
since arrays are zero indexed. I changed 2 to 1, since this is what you asked for.
I have tried to reset the values of r and c to zero but nothing changes.
This has no actual effect, since r and c are going to be overwritten upon next input.

C++ Printing Contents of array backwards One incorrect digit

As part of a program I'm trying to print the contents of an array in reverse order. It is working fine except for one value and I can't figure out why.
I haven't gotten onto functions yet so I haven't used them in my code here is the snippet
case 7:
for (int i = 11; i != -1; i--)// The variable i is initialised to 11. While i is not equal to -1 decrement i by 1.
{
infile >> list[i];//Read in values for array from data.dat
cout << list[i] << " ";// Outputting the array in reverse order.
outfile << "The array in reverse order is: " << list[i] << " " << endl;// Outputting the array in reverse order to file.
}
cout << endl;
break;
The array is filled with the following numbers
8 16 12 6 16 4 8 10 2 16 12 6
The expected output is:
6 12 16 2 10 8 4 16 6 12 16 8
The output I'm getting is:
6 12 16 2 10 8 4 16 6 12 6 8
Any help appreciated
The right way to reverse an iterator is to shift it down by one.
Forward:
T a[N];
for (std::size_t i = 0; i != N; ++i)
{
consume(a[i]);
}
Backward:
T a[N];
for (std::size_t i = 0; i != N; ++i)
{
std::size_t const ri = N - i - 1;
// ^^^
consume(a[ri]);
}
You can write a loop where you actually decrement the loop variable directly, but it's awkward since you either have to use signed integers or otherwise do an additional - 1 when using the index, and it's altogether unnatural, hard to read and easy to get wrong. I'd much rather recommend always using the forward-moving loop as shown here and compute the reverse iterator separately.
Incidentally, this logic is already encapsulated in the iterator wrapper std::reverse_iterator, which is build from a normal, bidirectional moving iterator but decrements by one when being dereferenced. You can either reverse a sequence yourself by using make_reverse_iterator, or by using the free rbegin/rend functions:
#include <iterator>
T a[N];
for (auto rit = std::crbegin(a); rit != std::crend(a); ++rit)
{
consume(*rit);
}

Variable Value Changes By Itself

I've been pretty confused while programming before, but this one takes the cake. Basically I set the value in one for loop, and in the following iteration it changes to the value of the next one.
for (int i = 0; i < 2; ++i)
{
for (int j = 0; j < numWords[i]; ++j) //numWords [0] = 9, numWords [1] = 7
{
stb[i][j].word = const_cast<char*>(is (j + 1,1).c_str()); //is(int,length[opt]) converts int to string, c_str() returns const char *, but I need char *
cout << is(j+1,1) << ' ' << stb[i][j].word << '\n';
}
}
for (int i = 0; i < 2; ++i)
{
for (int j = 0; j < numWords [i]; ++j)
{
cout << stb[i][j].word << ' ';
}
cout << '\n';
}
Output:
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
1 1
2 2
3 3
4 4
5 5
6 6
7 7
7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7
My only guess now is something with the const, but it doesn't make sense why it would keep changing all previous array elements...
This is pretty simple. Your program has undefined behaviour (if my assumptions about is() are correct).
is(int, length) returns a std::string by value. You get a pointer to some internal structure in that string by using c_str(). This string is then destructed at the end of the full-expression. This destruction invalidates the pointers that you obtained from c_str().
This means that you fill up the array with pointers to invalid memory. You then read from these pointers to print out the contents of the array. Reading from invalid memory results in undefined behaviour.
A possible explanation for the observed behaviour is this:
Each string that is returns reuses the same memory. In the first loop you read from the memory before it has been overwritten by another call to is, and so you get the correct value. In the second loop you read from the memory after it has been overritten, and so you get the final value in the array.