C++ for loop variable lifetime is weird - c++

for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
int n;
n++;
printf("n : %d\n", n)'
}
}
The output of the code is 1 2 3 4 5 6 7 8 9. I'm wondering why the variable n in the for loop isn't initialized when the variable declaration is executed.

You're never initializing n to a specific value. C++ will not do this by default when you call int n. Instead, it just reserves an integer sized block of memory. So when you call n++, the program is just grabbing whatever value happens to be in that memory and incrementing it. Since you're doing this in quick succession and not creating new variables in between, it happens to be grabbing the same memory over and over. As #NicolasBuquet points out, compiler optimization may also be responsible for the consistency with which the same chunk of memory is picked.
If you were to assign a value to n, (i.e. int n = 1;) this behavior would go away because a specific value will be written to the chunk of memory assigned to n.

In C++, no variable is initialized with a default value; you must specify one explicitly should you find the need to do so.
The result of your code is really undefined; it is just pure luck that you are getting the numbers 1 through 9 in sequence. On some other machine or implementation of C++, you might get different results.

Related

Initializing large 2-dimensional array to all one value in C++

I want to initialize a large 2-dimensional array (say 1000x1000, though I'd like to go even larger) to all -1 in C++.
If my array were 1-dimensional, I know I could do:
int my_array[1000];
memset(my_array, -1, sizeof(my_array));
However, memset does not allow for initializing all the elements of an array to be another array. I know I could just make a 1-dimensional array of length 1000000, but for readability's sake I would prefer a 2-dimensional array. I could also just loop through the 2-dimensional array to set the values after initializing it to all 0, but this bit of code will be run many times in my program and I'm not sure how fast that would be. What's the best way of achieving this?
Edited to add minimal reproducible example:
int my_array[1000][1000];
// I want my_array[i][j] to be -1 for each i, j
I am a little bit surprised.
And I know, it is C++. And, I would never use plain C-Style arrays.
And therefore the accepted answer is maybe the best.
But, if we come back to the question
int my_array[1000];
memset(my_array, -1, sizeof(my_array));
and
int my_array[1000][1000];
// I want my_array[i][j] to be -1 for each i, j
Then the easiest and fastest solution is the same as the original assumption:
int my_array[1000][1000];
memset(my_array, -1, sizeof(my_array));
There is no difference. The compiler will even optimze this away and use fast assembler loop instructions.
Sizeof is smart enough. It will do the trick. And the memory is contiguous: So, it will work. Fast. Easy.
(A good compiler will do the same optimizations for the other solutions).
Please consider.
With GNU GCC you can:
int my_array[1000][1000] = { [0 .. 999] = { [0 .. 999] = -1, }, };
With any other compiler you need to:
int my_array[1000][1000] = { { -1, -1, -1, .. repeat -1 1000 times }, ... repeat { } 1000 times ... };
Side note: The following is doing assignment, not initialization:
int my_array[1000][1000];
for (auto&& i : my_array)
for (auto&& j : i)
j = -1;
Is there any real difference between doing what you wrote and doing for(int i=0; i<1000; i++){ for(int j=0; j<1000; j++){ my_array[i][j]=-1; } }?
It depends. If you have a bad compiler, you compile without optimization, etc., then yes. Most probably, no. Anyway, don't use indexes. I believe the range based for loop in this case roughly translates to something like this:
for (int (*i)[1000] = my_array; i < my_array + 1000; ++i)
for (int *j = *i; j < *i + 1000; ++j)
*j = -1;
Side note: Ach! It hurts to calculate my_array + 1000 and *i + 1000 each loop. That's like 3 operations done each loop. This cpu time wasted! It can be easily optimized to:
for (int (*i)[1000] = my_array, (*max_i)[1000] = my_array + 10000; i < max_i; ++i)
for (int *j = *i, *max_j = *i + 1000; j < max_j; ++j)
*j = -1;
The my_array[i][j] used in your loop, translates into *(*(my_array + i) + j) (see aarray subscript operator). That from pointer arithmetics is equal to *(*((uintptr_t)my_array + i * sizeof(int**)) + j * sizeof(int*)). Counting operations, my_array[i][j] is behind the scenes doing multiplication, addition, dereference, multiplication, addition, derefence - like six operations. (When using bad or non-optimizing compiler), your version could be way slower.
That said, a good compiler should optimize each version to the same code, as shown here.
And are either of these significantly slower than just initializing it explicitly by typing a million -1's?
I believe assigning each array element (in this particular case of elements having the easy to optimize type int) will be as fast or slower then initialization. It really depends on your particular compiler and on your architecture. A bad compiler can do very slow version of iterating over array elements, so it would take forever. On the other hand a static initialization can embed the values in your program, so your program size will increase by sizeof(int) * 1000 * 1000, and during program startup is will do plain memcpy when initializing static regions for your program. So, when compared to a properly optimized loop with assignment, you will not gain nothing in terms of speed and loose tons of read-only memory.
If the array is static, it's placed in sequential memory (check this question). So char [1000][1000] is equal to char [1000000] (if your stack can hold that much).
If the array has been created with multidimensional new (say char(*x)[5] = new char[5][5]) then it's also contiguous.
If it's not (if you create it with dynamic allocations), then you can use the solutions found in my question to map a n-dimension array to a single one after you have memsetd it.

How does this array work

#include<iostream>
void main()
{int v[100],n,k;
cin>>n;
for(int i=0;i<n;i++) cin>>v[i];
k=0;
for(int i=1;i<n;i++)
if(v[i]==v[i-1]) k++;
cout<<k;}
Hey guys, I'm quite new to arrays and was wondering if someone could tell me what this line of code is doing:
int v[100],n,k;
If I'm right in my understanding, I am assuming that we are declaring a array with 100 possible values. However, what is n and k doing here? I saw a similar piece of code before, and it looked like it was programmed in a way such that the value of k would be inserted into our array n number of times.
Is my understanding there correct? I know what the rest of the code is doing but it's just that one line that is confusing.
Here, v is an array of int, while n and k are simple variables (scalars) of type int.
It's just a shorthand for:
int v[100];
int n;
int k;
You may declare severeal variables with the same declare spesifiers in one line. For example
int width, height;
Here there are two variables that are declared as having type int. You can also include an array declarator in the same line.
int width, height, sizes[100];
Here there are three variables, width, height, sizes, that are declared. Variable sizes is declared as an array.
It is equivalent to
int width;
int height;
int sizes[100];
v is an array with 100 elements.
n is the number of elements to look through (probably in the range [0, 100] or we'll run into out of bounds problems trying to accessing v[n] when n > 100)
k is used to count the number of times a value in v is equal to the next value in v.
So lets take an example in some kind of pseudo-code:
v = {0,3,3, ..., n};
// lets for simplicity say that n=3 (i.e. the number of integers I specified)
// the loop will run from 0 to n=3 both the outer and inner loop mind you..
The outer loop starts, i=0, k is set to zero because at this point we don't have any hits.
we start second loop with i=1 (no need to check i=0 since we don't want to check an entry against itself). And every time v[0] is equal to any of the other numbers in the set we will add one to k, so for our example: 0 != 3 and 0!=3 and k=0 will be the case, the program will print 0 and move on.
Second iteration i=1 and v[i] = 3. And the second loop starts to check v[1] against v[2] in this case both happen to be three and so k become one. and the iteration is done. the value 1 is printed and the loop continues.. and so it goes.
I would like to mention as well that the inner loop is creating a local variable int i=1; in the for-loop, I would be a bit careful with that since there might be compilers which can't scope it correctly and choose a different name for the loop index variable of the inner loop, traditionally one might use j but well both i and j could be argued to be bad names, but it's another discussion.
I hope it clears things up a bit.

Getting a memory address in my array?

I'm writing a C++ application that has a user enter a 0 (zero) or a one (1) as input, then stores the numbers as an array and sorts them so that the zeros come first and the ones come last.
However, I think I'm getting a memory address in my array that's messing up the sorting operation.
The function that accepts input looks like this:
cout << "Please enter number " << i+1 << ":\n";
cin >> ar[i];
Then there's a function that's called that sorts the input and displays the sorted list:
sort_elements(ar, number);
... and that function looks like this:
void sort_elements(int ar[], long int num_elements) {
int temp_num;
num_elements -= 1; //since the array starts at 0
cout << "num_elements is " << num_elements << "\n";
for (int i=0; i < (num_elements/2); i++ ) {
if (ar[i] > ar[num_elements-i]) {
temp_num = ar[i];
ar[i] = ar[num_elements-i];
ar[num_elements-i] = temp_num;
}
}
cout << "Here's your neatly sorted list of numbers: \n";
for (int j=0; j <= num_elements; j++) {
cout << ar[j] << ", ";
}
cout << "\n";
}
For a five number input, starting with three "1"s, and ending with two "0"s, this results in an output that looks like this:
1, 0, 1, 1, 1892218304,
I'm assuming the 1892218304 is a memory address, that's messing up the input. Though I don't really know.
Can anyone figure out why my sort operation is getting messed up?
Thanks in advance.
Suggestion
Use vector and sort in standard library
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
int main()
{
std::vector<int> v;
for(int i=0; i < 10; i++)
{
v.push_back(i);
}
std::sort(v.begin(), v.end());
return 0;
}
The number you are seeing is not a memory address, but the value of the 4 bytes either immediately before or immediately after your array, interpreted as an int. Your code has an off-by-one error that causes an access to just outside the array. That much I suspect even though I don't have proof.
However, I can't find anything wrong with the code you posted that would cause it to access outside the array bounds.
Are you sure that num_elements has the correct value when this function is called?
Update to address the pastebin code
Things are going wrong already from the start:
int number;
int ar[number]
This is called a variable-length array and it's not legal in C90 or any flavor of C++. That your program compiles is probably "thanks to" a compiler extension... which helpfully raises a bug: the value of number is not initialized before the array is allocated.
You need to do one of the following:
declare ar as an array of constant size (a hard limit on the number of inputs you can accept)
dynamically allocate ar with new[] after number is entered from the user
(by far preferable) use an std::vector instead of an array
It looks to me like you're just getting an uninitialized value in your output.
Under the circumstances, the simplest "sorting" method is probably a counting sort -- i.e., count the number of 0's and the number of 1's the user enters, and then print out the appropriate number of 0's followed by the appropriate number of 1's.
As Tony said, your sorting algorithm is incorrect.
If we assume the following values:
ar[0] = 0
ar[1] = 1
ar[2] = 0
ar[3] = 1
ar[4] = 0
that gives us num_elements equal to 5.
Running this through your function as written, we get the following sorting behavior:
First pass, i = 0
ar[0] > ar[4] -> not true, so no switch
Secon pass, i = 1
ar[1] > ar[3] -> not true, so no switch
There is no third pass, as your for loop condition is met
i = 2
num_elements/2 = 2
2 is not less than 2
So based on your code, you didn't sort anything. This is the first issue.
Your print problem is interesting, based on what you have shown num_elements has been decremented by 1 at the top of your code snippet in your function - therefore the <= condition is correct and you should not be outside the bounds of your 'ar' array. Are you sure this is the exact code, or perhaps you did not copy it properly here and you are actually having a scoping issue?
(EDIT: Although the other answers suggesting using a built in sorting method via vectors, I'd suggest you still work your current implementation out to figure out WHY this is wrong, and what you need to do to fix it. You will not always have an available type that has built in sorting, so understanding the fundamentals is important for any young programmer.)
EDIT2: Based on the link you provided, you aren't properly defining your integer array. You are defining the array based on an uninitialized integer (int ar[number]) when number has not yet been initialized. You then read a value from the standard input to set number, and assume your array has been dynamically adjusted to be of the size read from cin. It does not work this way. Your entire loop is reading/writing outside the bounds of your array which is a big no-no. You want to read the number first, and then define your array based on the size read. - Looks like Jon beat me again.. BAH! :P
The last element being read and printed to the screen has never been written to. I think it's likely your function which accepts input has a fault, like maybe you have a line like you have here
num_elements -= 1; //since the array starts at 0
at the input function so that the first element you write to is at address 1. Then when you're reading them you read from address zero.
I kind of agree with Jim's point: Use the facilities in the C++ standard library to finish your task as much as possible.
Besides, I suggest you go through the algorithm all by yourself, manually, instead of letting the computer run it for you. Ever heard of the "Rubber Duck Debugging Method"? :-) Have a try.

Array Initialization

I am trying to assign values within an array within the condition of a for loop:
#include <iostream>
using namespace std;
int* c;
int n;
int main()
{
scanf("%d", &n);
c = new int[n];
for (int i = 0; i < n; c[i] = i++ )
{
printf("%d \n", c[i]);
}
return 0;
}
However, I am not obtaining the desired output, for n = 5, 0 1 2 3 4. Instead, if I am using the instruction, c[i] = ++i, I am obtaining the output -842150451 1 2 3 4. Could you please explain me we does my code behave like this and how can I correct it?
The value of the expression ++i is the value after i has been incremented. So if it started at 0, you assign value 1 the first time and so on. You can see where the value got assigned, but asking why it got assigned there opens a can of worms.
Using i in an expression where i is modified via i++ or ++i is undefined behavior unless there is a so-called "sequence point" in between the two. In this case, there isn't. See Undefined behavior and sequence points for this rather complicated part of the language.
Although the behaviour is undefined by the standard, and may not be consistent from one run to another, clearly your program has done something. Apparently it didn't assign to index 0 at all (at least, not before the first print, which is understandable considering that the loop body happens before the last part of the "for"), so you got whatever just so happened to be in that raw memory when it was allocated to you. It assigned 1 to index 1 and so on.
This means that it may also have attempted to assign the value 5 to c[5], which is a class of bug known as a "buffer overrun", and more undefined behavior on top of what you've already got. Attempting to assign to it probably overwrites other memory, which on any given day may or may not contain something important.
The fix is to assign some value to c[0], and don't try to assign to c[5], which doesn't exist anyway, and don't try to invalidly use i "at the same time as" incrementing it. Normally you'd write this:
for (int i = 0; i < n; ++i) {
c[i] = i;
printf("%d \n", c[i];
}
If you're desperate for some reason to assign in the third clause of a for loop, you could use the comma operator to introduce a sequence point:
for (int i = 0; i < n; c[i] = i, ++i) {
}
But of course if you do that then you can't print the value of c[i] in the loop body. It hasn't been assigned yet, because the third clause isn't evaluated until the end of each loop.
You could also try c[i] = i+1, ++i, but not ++i, c[i] = i because then we're back to trying to assign to c[5], on the last iteration.
First you need to understand that the last part of the for loop is executed at the end of each iteration, so the reason you see this:
-842150451 1 2 3 4
Is because you print c[0] before it is assigned, so the value could be anything. The rest falls into line as expected.
Lesson; don't be sneaky and stuff things into the last part of the for loop like that. Make your code clear and simple:
for (int i = 0; i < n; ++i )
{
c[i] = i;
printf("%d \n", c[i]);
}
Firstly, you are claiming that you want to assign the values "within the condition of the loop". In for loop the condition is the second part of the header (i < n in your case). You are performing the assignment in the third part, which is not a condition. So, why are you saying that you want to assign the values within the condition, and yet not doing that?
Secondly, expressions like c[i] = i++ or c[i] = ++i do not have any defined behavior in C++ language. In C++ it is illegal to modify a variable and at the same time read it for any other purpose without an intervening sequence point. Yet, you are doing exactly that. There's no meaningful explanation for the behavior of your code. The behavior of your code is undefined. It can do anything for any random reason.
Thirdly, initializing anything in the for condition is generally not a good idea. Could you explain in more detail what you are trying to do and why? Without it it is hard to come up with anything meaningful.
Your fundamental problem is how the statements in the for(;;) structure get broken down and executed. The for(st1; st2; st3) structure is intended to be identical to:
st1;
while (st2) {
<body>
st3;
}
Therefore, your 3rd statement, c[i] = i++, gets executed after the printf statement and you're printing uninitialized data.
The pre-increment vs. post-increment issue is obscuring this.
The reason why c[i] = ++i produces undefined behavior. It's undefined to both ++ a value (pre or post) and use it again within the same expression. In this case it appears that ++i is being evaluated before anything else and causing the execution to essentially be
c[1] = 1;
c[2] = 2;
...
This means c[0] is never initialized and instead has essentially a garbage value. It seems like the order you want is
c[0] = 0;
c[1] = 1;
To get this ordering you'll need to separate the initialization and increment into separate statements.
c[i] = i;
i++;

Array index loop variable resets to zero in C, C++

I have declared an array of length N (suppose). Now, I assign some values to the elements of this array using a loop (the loop variable is used as the array's index). The code's as follows:
int main()
{
int arr[4], j;
for(j=0; j<10; j++)
{
printf("%d\n", j);
arr[j] = 0;
sleep(1);
printf("%d\n\n", j);
}
return 0;
}
I expected the output to be 0 1 2 .. 9. But what actually happened was that j got reset to 0 when the assignment arr[N+2]=0 (arr[6]=0, in this case) was executed in the loop.
What's actually happening here? Am I missing something?
Your array has 4 elements and your index is out of range so you are just stomping on memory.
Given the code here, I'd expect arr[4] to reset the array, but since you mentioned that it's of length N and N+2 is what causes it, there might be some padding in your stack. In any case, when you declare the array and j, they are put on the stack. In your case, j is in a position such that when your index is out of bounds you are accessing the memory where j is.
the behaviour of the code is undefined as it has a bug. arr has a size of 4 but you are indexing past this size with j
Your array is overflowing. You defined it like this with 4 elements:
int arr[4]
But you're trying to assign 10 elements.
j is apparently located immediately after the array, so when you assign arr[6] = 0, you're clearing j.