Strange behavior of C++ array size - c++

I am writing a c++ function to calculate the size of an C-type array in C++
I noticed a very strange behavior when using these two different codes:
code 1:
int sz = sizeof array / sizeof *array;
code 2:
int array_size(const int *pointer)
{ int count=0;
if(pointer)
while(*pointer) {
count++;
pointer++;
}
return count;
}
When I applied these two method on a array, it gave me very strange behavior:
example 1 :
int array[10] = {31,24,65,32,14,5};// defined to be size 10 but init with size 6
the code one will give me size = 10, but code 2 will give me size 6,and when I print out the element that is pointed by *pointer, it will give me the correct array elements:
31 24 65 32 14 5
example 2
int array[] = {31,24,65,32,14,5}; // no declared size but init with 6
Code 1 will give me size 6, code 2 will give me size 12, and when I print out the element that is pointed by *pointer in code 2, it gives me :
31 24 65 32 14 5 -802013403 -150942493 1461458784 32767 -1918962231 32767
which is really not right, so what could be the problem that cause this behavior? and what are those numbers?
Thanks for your answer

This array has 10 elements, regardless of how you initialize it:
int array[10] = {31,24,65,32,14,5};
But the initialization sets the first 6 elements to certain values, and the rest to 0. It is equivalent to this:
int array[10] = {31,24,65,32,14,5,0,0,0,0};
The first calculation using sizeof uses the actual size fo the array (its length times the size of an int), while the second one counts elements until it finds a 0. So it doesn't calculate the length of the array, but the length of the first non-zero sequence in the array.
Note that the second method only "works" if the array has an element with value 0. Otherwise you go out of bounds and invoke undefined behaviour.

array_size assumes that there is a 0 just past the end of the array. That assumption is unjustified.

code 2 is not right. you can't assume an array end with 0

Related

vector <pair<int,int>>v(size); showing 0 as values when printed

C++: vector<pair<int,int>>v(size); showing 0 as values when I am trying to print out the values, but when the vector size is not declared it is showing correct output? Why so?
For example:
int x;
cin>>x;
vector<pair<int,int>>v(x); //Size declared.
for(int i=0;i<x;i++){
int p,q;
cin>>p>>q;
v.push_back(make_pair(p,q));
}
But when I am trying to print the values, it is printing 0 only.
I/P->
3
1 2
3 4
5 6
O/P->
0 0
0 0
0 0
But when I don't declare the size of the vector it prints the output without any error, why is that?
i.e
int x;
cin>>x;
vector<pair<int,int>>v; //Size is not declared.
for(int i=0;i<x;i++){
int p,q;
cin>>p>>q;
v.push_back(make_pair(p,q));
}
I/P->
3
1 2
3 4
5 6
O/P->
1 2
3 4
5 6
It shows the correct output. Why is that?
It is because the vector's constructor accepting an integral (it is of type size_t) does not only provide sufficient size, but creates x default objects. You then append your new objects to these default ones.
Be aware that the term 'size' in STL wording refers to the number of elements already inserted/contained, the total number of elements that can be held without re-allocation is referred to as 'capacity'.
If you want to pre-allocate sufficent capacity without creating new objects, you need to use reserve:
std::vector<std::pair<int,int>> v;
v.reserve(x);
Vector constructor with int means it create that many elements. They are pairs of zeroes. Then you push back and it creates new elements at the end. So all elements are X * 2.
I am assuming then you do not check the size, but instead you list first X elements.
You can fix by either vector::reserve(x) or by using []instead of pushing back. Then operation will look more like array access.
Because element is pair of int, both options are good.
Reserve is faster, array like access is more generic.

How does C++ find the size of an array?

Difference From Other Questions
I am not asking how to find the size, but how the computer finds the size.
Goal
I want to find out how C++ finds the size of an array (using sizeof(array)), and a 2D array (using sizeof(array)).
When I ran the code, I thought the output would be 3 and 6. But it was 12 and 24!? How do I make the the output 3 and 6?
I don't know how to calculate the size of an array, so when I say "an output of three/six", I mean the amount of numbers in the array.
Code
#include <iostream>
using namespace std;
int main()
{
int oneDArray [3] = {1, 2, 3};
int twoDArray [2][3] = {{1, 2, 3}, {1, 2, 3}};
cout << sizeof(oneDArray) << "\n" << sizeof(twoDArray);
return 0;
}
The sizeof operator returns the size in bytes, not elements.
For single dimensional arrays (not passed as a function argument, which would cause decay to a pointer), you can get the element count by dividing the size of the array by the size of the first element, e.g.
sizeof(oneDArray) / sizeof(oneDArray[0]) // Gets 3
For multidimensional arrays, that would tell you the size of the first dimension, not the number of elements total, so you'd need to drill down deeper:
sizeof(twoDArray) / sizeof(twoDArray[0]) // Gets 2 (first dimension of array)
sizeof(twoDArray) / sizeof(twoDArray[0][0]) // Gets 6 (number of elements)
You can of course explicitly name the type of an element to avoid nested indexing (sizeof(twoDArray) / sizeof(int) get 6 just fine), but I avoid it as a rule; it's too common for an array to change types during development (say, it turns out you need to use int64_t because you have values into the trillions), and if the whole expression isn't in terms of the array, it's easy to overlook it and end up with broken code.
sizeof returns bytes, if you expect number of elements, divide by the size of each element
cout << sizeof(oneDArray)/sizeof(int) << "\n" << sizeof(twoDArray)/sizeof(int);
Output:
3
6

fill_n() is not letting change variable value

I am using fill_n() function to initialize my array values, but then I cannot change the values of the array, it is always the initial value.
Can someone explain me why is that?
#include<iostream>
#include<ctime>
int main(){
//Matrix
int m[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
int v[3] = {5,6,7};
int result[3];// = {0,0,0};
int n = 0, i, j;
std::fill_n(result,sizeof(result),0);
clock_t time = clock();
while(n<1000){
n++;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
result[j] = result[j]+(v[i]*m[j][i]); //changing the values here.
}
}
}
time = clock() - time;
for(i=0;i<3;i++){
std::cout<<result[i]<<"\n";
}
std::cout<<"Execution time: "<<((float)time)/CLOCKS_PER_SEC<<"\n";
return 0;
}
The output of the code is always 0.
By std::fill_n(result,sizeof(result),0); you are asking to fill the first sizeof(result) elements by 0.
However, only 3 elements are available in result. Thus you wrote out-of-bound and led to undefined behavior. You should write std::fill_n(result, sizeof(result) / sizeof(result[0]), 0); instead.
Note that sizeof(result) returns size of result in bytes, not in elements.
sizeof(result) returns the number of bytes held by the variable result. Since result is an array of 3 ints, its size in memory is 3 * sizeof(int), which (unless sizeof(int) is 1) much greater than 3. Thus you are writing pass array bounds and incurring undefined behavior.
The actual way to calculate the size would be to divide the entire size of result by its element type. That is, sizeof(result) / sizeof(int).
If you want to initialize each element to 0, a simpler way to do it would be to value-initialize the array:
int result[3]{}; // or = {} (pre C++11)
Number of elements (or size) of an array of type type would be sizeof(array) / sizeof(type). Second argument required for fill_n is the number of elements to fill a container (in your case, an array of type int) and not the size of an array in bytes. Naturally, sizeof(array) returns sizeof(type) times number of elements.

Incorrect output using array as counter

I'm trying to teach myself programming by attempting problems from codeabbey.com.
I'm not getting the correct output on this question.
Question:
Here is an array of length M with numbers in the range 1 ... N, where N is less than or equal to 20. You are to go through it and count how many times each number is encountered.
Input data contain M and N in the first line.
The second (rather long) line will contain M numbers separated by spaces.
Answer should contain exactly N values, separated by spaces. First should give amount of 1-s, second - amount of 2-s and so on.
Data input:
10 3
1 2 3 2 3 1 1 1 1 3
Correct Output:
5 2 3
My Output:
7 3 4
You can check here
My Code:
#include <iostream>
using namespace std;
int main()
{
int arrayLength,range,a;
cin>>arrayLength>>range;
int array[20];
array[20]={0};
for(int i=0; i<arrayLength; i++)
{
cin>>a;
++array[a-1];
}
for(a=0; a<range; a++)
{
cout<<array[a]<<" ";
}
return 0;
}
There aren't any error messages or warnings. Also, if you have any suggestions for improving the code, that'd be nice.
int array[20];
array[20]={0};
is wrong, since it leave the array un-initialized and tries to initialize the 21st element (which is undefined behaviour btw, since your array has only 20 elements, remember that indexing starts from 0). Use
int array[20] = {0}; // this will initialize all elements to 0
and your code will work as expected. See here for more details regarding aggregate initialization in C++.
array[20]={0}; initializes the 21st element(non-existing) to 0.
So you have to use int array[20] = {0}; which will initialize all 20 elements to zero.
Also from your code, you are not storing the elements to an array. You are just incrementing the corresponding count when an input is read. If so, what is the need of initializing an array to max limit. Just declare the array as you need it. In your case,
int array[range] = {0};
It will initialize an array of three (range =3 here) elements.

Pointers of arrays

#include<iostream>
#include<iomanip>
void main()
{
int i,j;
int pole[3][3]={1,2,3,4,5,6,7,8,9};
*(*(pole+2)+2)=0;
for(i=0; i<3;i++)
{
for(j=0;j<3;j++)
{
cout << setw(5)<< pole[i][j];
}
cout << endl;
}
}
This is my program and the output I get is the following:
1 2 3
4 5 6
7 8 0
However, I have troubles understanding what exactly does this line mean:
*(*(pole+2)+2)=0;
In my understanding, it's a pointer to pointer of array, so basically, the first we do:
*(pole+2)
which points to the 2nd element of the array. Then
*(*(pole+2)+2)
which points to the 4th element of the array? Is this correct? If so, how do we change the last [3][3] element to 0?
Thank you.
Here pole is a 2D array of 3 rows and 3 columns. So as array index starts from 0, you are assigning pole[2][2] = 0 which actually means 0 is assigned to 3rd row and 3rd column element.
*(*(pole+2)+2) == *(pole[2] + 2) == pole[2][2]
I just learned about pointers in and arrays in depth in my C++ so i hope i can help
you declared a 2D Array which is really just an array of an array of int types.
(pole + 2) points to pole's base address and adds 2(size of an array of ints) to it so:
2*int(4 bytes) * 3(size of array) = 24 bytes
so it adds 24 bytes to the address. it is now pointing to the 3rd array. then it takes that and points to:
3rd arrays base address + 2*int(4bytes)
which will lead it to the 3rd index of that array which is 9. It then changes this value to 0.
the key is that the first pointer is pointing to an Array of arrays. the second pointer points to the index inside of that array.
I hope i didn't confuse you.