For loop condition is a variable without comparison - c++

int a[5] = {1,2,3,4,5};
for (int i = 0; a[i]; i++)
{
cout << i;
}
This code produces the output of "0 1 2 3 4".
What does it compare a[i] against, and how does it know to stop at the end of the array and not go over?

You code causes undefined behaviour. The expression a[i] will evaluate as true if non-zero and as false if zero. When you run it, you're getting lucky that there is a 0 word immediately following your array in memory, so the loop stops.

It's reading past the array and the memory there just happens to be zero, by sheer luck. Reading past the end of that array is undefined behavior and the outcome might change at any time, so never rely on it.

You can think of a[i] as being compared to 0, it simply fetches the number retrieved from the location in memory and if 0 is the value that lives at that memory, then the loop exits, if it is any other number the loop continues.
Suppose an int is 4 bytes on the system. a is given an address, lets pretend it is 0xFF00 when we try to evaluate a[0] we retrieve the data value stored at memory 0xFF00. a[1] would retrieve data from memory 0xFF04, etc. Your program only assigns values to the first 5 memory locations, so when we retrieve the data at beyond these locations they could be anything from 0 to INT_MAX. If it happens to be 0 then the loop exits, however if it happens to be something else the loop continues.
Your could adjust your program like so to see it better:
#include <iostream>
using namespace std;
int main() {
int a[5] = {1,2,3,4,5};
int i;
for (i = 0; a[i]; i++)
{
cout << "At memory address: " << &a[i]
<< " lives the value: " << a[i] << endl;
}
cout << "At memory address: " << &a[i]
<< " lives the value: " << a[i]
<< ", and this is why the loop ended." << endl;
return 0;
}

Related

why after pop_back() operation it still prints the complete vector?

I have the following main program that creates a Stack object, fills it with integers and then pops them. The code files fine, but the pop_back() part does not seem to work, even after pop_back() it prints all values. How is this possible?
#include<iostream>
#include<vector>
using namespace std;
int main(){
vector<int> myVector; //initalization
int value;
//input in a vector using push_back
for (int i = 0; i < 6;i++){
cin >> value;
myVector.push_back(value);
}
cout<<"Initial vector size:" << myVector.size() <<endl;
for (int i = 0; i < 6;i++){
cout << myVector[i];
}
cout << endl;
myVector.pop_back();
cout<<"Vector size after pop back: " << myVector.size() << endl;
cout << endl;
cout << "First element is: " << myVector.front() << endl;
cout << "Last element is : " << myVector.back() << endl;
for (int i = 0; i < 6;i++){
cout << myVector[i];
}
return 0;
}
Everyone has focused on saying this is undefined behavior fix code, but question was why it works.
To understand why it works you must understand how vector works more or less.
Vector allocates some block of memory to store items.
size of this block is defined by capacity, which says how many items can be stored in vector, without allocating new block of memory
capacity is usually bigger then size of the vector
now when you remove items form vector, capacity and allocated block of memory doesn't change. This is an optimization.
when you remove item from back just destructor is called (for int it does nothing) and size of vector is reduced.
your value is not cleared just marked as out of vector size
so when you use operator[] it doesn't check if you exceed its size. It just returns value at specific adders
since pop_back just reduced size you value is still there
Note if you call shrink_to_fit after pop_back there is a great chance it will and with crash or you will not receive same value. Still this is undefined behavior and anything can happen.
Another way to see your code is bad is to use at which checks if index is in valid range.
std::vector::pop_back function works just fine. After you perform a call to it, you try to print all 6 values instead of 5. Therefore, you are accessing invalid memory. In your case, program prints out the value that was removed but in some other case it could print some garbage value. That's why this is UB - Undefined Behavior.
Try the following and you will see that last element is not in the std::vector:
for (int i = 0; i < myVector.size(); i++) {
std::cout << myVector[i];
}
or, even better, use range-based for loop:
for (auto const i : myVector) {
std::cout << i;
}
The problem is in the way you loop through the vector - you are expecting it to have 6 elements even after you have removed the last element. This is undefined behavior.
Using a range based for would be preferred in both cases where you want to output the contents of the vector:
for (auto i:myVector) {
cout << i;
}

Extra number while looping through an array in C++

I am trying to loop through an array of integers using pointers using the following code:
#include <iostream>
int main (int argc, char ** argv)
{
int ar[] = {1,1,2,3,5,8,13,21,34,55};
char s[] = "string";
std::cout << "Print fibonacci until ten using pointers" << std::endl;
for (int * p = ar; *p; p++)
{
std::cout << *p << std::endl;
}
// for (char * cp = s; *cp; cp++)
// std::cout << "char is " << *cp << std::endl;
return 0;
}
On running this code, I get all 10 elements plus a number, 4196368.
But on uncommenting the second for-loop and running it again, the numbers vanishes.
Can someone explain why this happens? If needed, the code is compiled in a 64-bit Linux box.
You're lucky the loop stopped at all; you could have blown up your entire neighbourhood!
Your loop expects to find a "zero" to terminate the array iteration, but your array doesn't have one. Thus, your loop will just keep incrementing past the end of the array until god knows what. The practical results depend on too many practical factors to be either predictable or usefully explained.
I presume that this is an exercise, because using "null-termination" to iterate over an int array is mighty peculiar. In reality you'd just write:
for (auto x : ar)
std::cout << x << '\n';
}
You are invoking an undefined behavior.
The first for loop's termination condition is *p. So it is trying to access memory past what actually is owned by ar. Your loop then runs until it finds a memory location that contains 0 (read false) before terminating. In your case, it ran just one extra time (lucky you!). At my end, it ran four more times before terminating.
You must loop only as many times as the size of the array, which is sizeof(ar)/sizeof(ar[0])
Ensure that you have terminated zero:
int ar[] = {1,1,2,3,5,8,13,21,34,55, 0};
Well, actually this will result in a different outcome on a different machine or a different condition. The one that causes this is your for statement
for (int * p = ar; *p; p++)
{
std::cout << *p << std::endl;
}
Here, you used *p as a conditional for your for loop to keep running. As we know, C++ treat number > 0 as a true and 0 as a false. While in the for statement, your program checks the next memory address if the value in that address is zero or not (True or False). And as you know, the value of the next address in this particular case on your particular PC is 4196368. So the for loop keeps going until the value of the next address is zero. You can see this with printing the address.
for (int * p = ar; *p; p++)
{
std::cout << *p << " " << p << std::endl;
}
You will know here that your code check the next address to see its value an if it is indeed not zero, it will continue the loop.

C++11 Why does cout print large integers from a boolean array?

#include <iostream>
using namespace std;
int main() {
bool *a = new bool[10];
cout << sizeof(bool) << endl;
cout << sizeof(a[0]) << endl;
for (int i = 0; i < 10; i++) {
cout << a[i] << " ";
}
delete[] a;
}
The above code outputs:
1
1
112 104 151 0 0 0 0 0 88 1
The last line should contain garbage values, but why are they not all 0 or 1? The same thing happens for a stack-allocated array.
Solved: I forgot that sizeof counts bytes, not bits as I thought.
You have an array of default-initialized bools. Default-initialization for primitive types entail no initialization, thus they all have indeterminate values.
You can zero-initialize them by providing a pair of parentheses:
bool *a = new bool[10]();
Booleans are 1-byte integral types so the reason you're seeing this output is probably because that is the data on the stack at that moment that can be viewed with a single byte. Notice how they are values under 255 (the largest number that can be produced from an unsigned 1-byte integer).
OTOH, printing out an indeterminate value is Undefined Behavior, so there really is no logic to consider in this program.
sizeof(bool) on your machine returns 1.
That's 1 byte, not 1 bit, so the values you show can certainly be present.
What you are seeing is uninitialized values, different compilers generate different code. On GCC I see everything as 0 on windows i see junk values.
generally char is the smallest byte addressable- even though bool has 1/0 value- memory access wise it will be a char. Thus you will never see junk value greater than 255
Following initialization (memset fixes the things for you)
#include <iostream>
using namespace std;
int main() {
bool* a = new bool[10];
memset(a, 0, 10*sizeof(bool));
cout << sizeof(bool) << endl;
cout << sizeof(a[0]) << endl;
for (int i = 0; i < 10; ++i)
{
bool b = a[i];
cout << b << " ";
}
return 0;
}
Formally speaking, as pointed out in this answer, reading any uninitialized variable is undefined behaviour, which basically means everything is possible.
More practically, the memory used by those bools is filled with what you called garbage. ostreams operator<< inserts booleans via std::num_put::put(), which, if boolalpha is not set, converts the value present to an int and outputs the result.
I do not know why you put a * sign before variable a .
Is it a pointer to point a top element address of the array?

C++ (g++ compiler) Dynamically Initializing Statically Declared Array Leads to Memory Questions

We went over differing compiler behavior today in my data structures class. The example below (plus some of my cout'ing and other tinkering) was given as a program that could compile on g++ but not necessarily on all other compilers.
#include <iostream>
using namespace std;
int main(void)
{
int i;
int j = 5;
cout << "i address: " << &i << " -- j address: " << &j
<< endl << "enter size: ";
cin >> i;
cout << "value i: "<< i << "; size memory of i (ints): "<<(&i - &j)<< endl;
int a[i];
cout << "address of array a start: " << a << endl;
int b = 14;
cout << "value b: " << b << "; b address= " << &b << endl
<< "distance bt j and b(ints): "<< (&j - &b) << endl;
cout << "distance bt b and start of array(ints): " << (&b - a) << endl;
}
After playing around with inputs (and learning a little about how dynamic arrays are allocated memory in the process), I decided that entering 0 was the most interesting. The output:
i address: 0x7fff5b303764 -- j address: 0x7fff5b303760
enter size: 0
value i: 0; size memory of i (ints): 1
address of array a start: 0x7fff5b3036b0
value b: 14; b address= 0x7fff5b303754
distance bt j and b(ints): 3
distance bt b and start of array(ints): 41
My Questions:
How does g++ know to treat the array a as one which needs to be dynamically created vs immediately trying to statically create one with whatever the default value of i is or throwing some sort of compile time error?
The distance between j and b is 3 ints worth of memory instead of the expected 1. What is going on with that? I suspect, purely from empirical evidence gathered by playing around with the program, that it has something to do with the couts, but I'm unfamiliar with how/why they would be stored in memory in seemingly random amounts.
I entered 0 for size of array a and, based on playing around with different sizes, I think it is unlikely that a dynamic array of length 0 would be initialized to length 41. So, if it is not the array taking up all of those 41 ints worth of memory, what then is stored between b (the last data stored on the stack) and the array a (the first data purposefully stored on the heap) and why is whatever it is there?
a is a variable-length array which is not part of standard C++ but a g++ extension. g++ knows that it is not a regular array with size determined at compile-time, because i is not a compile-time constant, such as const int i = 3; a is not stored on the heap. It is stored on the stack. I imagine the address distance between j and b depends on the size allocated to a, which can only be known at run-time. I don't know how to account for the distance between b and a for size 0. If you built in debug-mode, it's possible that some extra hidden buffer was added after the array in order to detect an accidental overwrite beyond the bounds of the array.

c++ vector not updating in nested for loop

So I create and initialize a vector (of size nmask+3) to 0, and I assign an initial value to one of the elements. I then make a for loop that goes through the first nmask elements of the vector and assigns to each element an average of 26 other elements in the vector (defined by the 4D int array voxt, which contains vector addresses).
My problem is that when I check the values of nonzero elements in my vector (phi) within the nested loop (the first cout), the values are fine and what I expect. However, when the loop finishes going through all nmask elements (for (int i= 0; i<nmask; i++) exits), I check the nonzero elements of phi again, and they are all lost (reset to 0) except for the last non-zero element (and element tvox which is manually set to 1).
I feel that since phi is initialized outside of all the loops, there should be no resetting of values going on, and that any updated elements within the nested loop should remain updated upon exit of the loop. Any ideas as to what is going on / how to fix this? Code is below; I tried to comment in a sense of the outputs I'm getting. Thanks in advance.
vector<double> phi(nmask+3, 0); //vector with nmask+3 elements all set to 0 (nmask = 13622)
phi[tvox]= 1; //tvox is predefined address (7666)
for (int n= 0; n<1; n++)
{
vector<double> tempPhi(phi); //copy phi to tempPhi
for (int i= 0; i<nmask; i++)
{
for (int a= -1; a<=1; a++)
{
for (int b= -1; b<=1; b++)
{
for (int c= -1; c<=1; c++)
{
if (!(a==0 && b==0 && c==0))
{
//oneD26 is just (double) 1/26
phi[i]= tempPhi[i]+oneD26*tempPhi[voxt[i][1+a][1+b][1+c]];
if (phi[i]!=0)
{
//this gives expected results: 27 nonzero elements (including tvox)
cout << n << " " << i << " " << a << b << c << " " << phi[i] << endl;
}
}
}
}
}
}
phi[svox]= 0; //svox = 7681
phi[tvox]= 1;
for (int q= 0; q<nmask; q++)
{
//this gives only 2 nonzero values: phi[tvox] and phi[9642], which was the last nonzero value from 1st cout
if (phi[q]!=0)
cout << q << " " << phi[q] << endl;
}
}
Difficult to tell just what is going on, but the easiest explanation is that after phi[i] gets set to non-zero and displayed to cout, it gets set to zero again in one of the later iterations through the inner loops.
If you do some tracing and check phi[i] just before updating you'll see that you often overwrite a non-zero element with zero.
Note: I have no idea what your code does, this is pure Sherlock Holmes reasoning.. if after the loops you find only 2 non-zero elements then the only logical consequence is that after updating something to non-zero later in the loop you update it to zero.
phi[i]= tempPhi[i]+oneD26*tempPhi[voxt[i][1+a][1+b][1+c]];
The nested for-loops using a, b, and c run for a combined 9 iterations with the same value of i. Since you overwrite phi[i] to a new value every time, you only retain the value from the last iteration where a, and c are all 1. If that last iteration happens to produce zero values, then phi[i] will have lots of zeroes. Perhaps you meant to do something like phi[i] += ... instead of phi[i] = ...?
I do suggest to replace the meat of the loop with something like
const boost::irange domain(-1,2);
for (int i: boost::irange(0, nmask)) for (int a: domain) for (int b: domain) for (int c: domain)
{
if (a==0 && b==0 && c==0)
continue;
//oneD26 is just (double) 1/26
phi[i]= tempPhi[i]+oneD26*tempPhi[voxt[i][1+a][1+b][1+c]];
if (phi[i]!=0)
{
//this gives expected results: 27 nonzero elements (including tvox)
cout << n << " " << i << " " << a << b << c << " " << phi[i] << endl;
}
}
Of course, for brevity I assume both boost/range.hpp and c++0x compiler. However, with trivial macro's you can achieve the same. That is without writing/using a proper combinations algorithm (why is that not in the standard, anyway).