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

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

Related

Array larger than specified size in C++ [duplicate]

This question already has answers here:
c++ sizeof(array) return twice the array's declared length
(6 answers)
How do I find the length of an array?
(30 answers)
Closed 4 years ago.
When testing an array like this:
float test [3] = {1, 2, 3};
cout << "Test size: " << sizeof(test) << endl;
The size shown by the print statement is 12. Similarly, when I made the size 12, the number of elements in the array was 47. Isn't this the correct way to specify the size of an array in C++?
sizeof doesn't return the number of elements in the array, it returns the memory size in bytes. Since your array contains three regular integers, and integers are 4 bytes in size, that's 3 * 4 == 12 bytes.
To get the length of the array, you have a few options:
Option 1
int size = sizeof(test) / sizeof(test[0]);
What that does is get the size of the array (which is 12 bytes) then divides that by the size of a single element (which is 4 bytes). Obviously 12 / 4 == 3.
Option 2
As pointed out by #PaulMcKenzie, if you're able to use C++17 you can use std::size. That makes it very easy because you can just do this:
int size = std::size(test);
Option 3 (Not recommended)
int size = *(&test + 1) - test;
Which is a clever hack using pointers, explained here. Will result in undefined behaviour and may break, depending on the compiler and its optimisations.
If you want the more efficient way of calculating the number of elements in an array, you could use templates.
template<typename T, std::size_t Size>
std::size_t GetArrLength(T(&)[Size]) { return Size; }
If we call it as such:
float test[3] = {1,2,3};
GetArrLength(test);
The compiler will try to deduce the template parameters. For the parameter type to match what you're passing, T must be float and size must be 3 (making the parameter a reference to an array of 3 floats).
You must use following way to get the actual size of array you requires.
int size = sizeof(test)/sizeof(test[0]);
sizeof() actually returns no. of bytes. So, you get the no. of bytes in your array object. To get actually the no. of elements, we need to divide it by the size of an element there. For example, here sizeof(float)
You need to divide the single element size to get the array size.
int sz = sizeof(test) / sizeof(test[0]);
cout << "test size: " << sz << endl;
This will work :
size_t n = sizeof(test)/sizeof(test[0]);
size_t is a type guaranteed to hold any array index, so use size_t.
The standard library has a type trait for this purpose.
#include <type_traits>
#include <iostream>
int main()
{
float test [3] = {1, 2, 3};
std::cout
<< std::extent<decltype(test)>::value
<< '\n';
}

Memory allocation for a 2D array in c++

I'm new to c++ and trying to understand how memory allocating is done for 2D arrays.I have gone through several threads in SOF and these answers.
answer1
answer2
Those answers says that continuous memory allocation happen for 2D arrays as well like for normal arrays. (correct me if I'm wrong) Answer 2 mention that it should be able to access array[i][j] th element using*(array + (i * ROW_SIZE) + j)
But when I'm trying to do that it gives me an unexpected result.
Code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int array[2][2] = { {1, 2}, {3, 4} };
cout<<*((array+1*2) + 1)<<endl;
cout<<**((array+1*2) + 1)<<endl;
return 0;
}
Result:
0x76e1f4799008
2012576581
It doesn't give me array[i][j] th element. Can some one explain what is happening here, whether that solution is wrong or have i misunderstood the previous answers.
First you have to get a pointer to the first element of the whole thing, i.e. not just to the first row:
int *p = &array[0][0]
After that, you can index p like you want:
std::cout << *(p + 1*2 + 1) << std::endl;
The reason why your initial tries didn't work is related to types. What is happening is that in your first try you are trying to evaluate
*(array + 1*2 + 1)
Now since, array is of type "array-of-length-2" containing "array-of-length-2" containing ints, i.e. (int[2])[2] what this will do is increment array with 3 times the size of its elements, which in turn are int[2]. This will jump outside of your array. In fact *(array+3) is equivalent to array[3]. Now, that clearly is something with type int[2], which will decay to a pointer when you try to print it. In your second try, you dereference this, yielding something like array[3][0], which now is of the right type, but again, points outside of the array.
it is more like when you simulate a 2d array as a one dimensional array like this
0 1 2
3 4 5
6 7 8
and the array will be 0 1 2 3 4 5 6 7 8 to access 4 it should be *(a[0]+(1*3)+1)a[0] is the same as a(name of array).
array is 2D pointer
**array = array[0][0]
*(*array + j) = array[0][j]
*(*(array+i) + j) = array[i][j]

C++ Arrays and overflow

I am mis-understanding something about the code below. From my understanding the tester declaration should return a pointer to the first array of two elements, i.e. [1,2], and so *(tester+1) should return [3,4], which only has 2 elements so how does it make sense to call (*(tester + 1))[2] . This example prints the number 5 by the way. Any clarifications much appreciated.
int main() {
int tester[][2]{ 1,2,3,4,5,6 };
cout << (*(tester + 1))[2] << endl;
return 0;
}
When you declare a 2-dimensional array, all the elements are contiguous. The entire array is a single object, so you're not going out of bounds when you just exceed one of the row limits, so longer as you're still in the array. So the next element after tester[1,1] is tester[2,0], and that's what (*(tester + 1))[2] accesses.
[2] is higher than the highest element at [1] because the index starts at [0]
There are three arrays.
[1,2] positions 0,0 and 0,1
[3,4] positions 1,0 and 1,2
[5,6] positions 2,0 and 2,1
Since all of the arrays are next to each other in the data segment, going out of bounds on the second array (tester + 1) bleeds over into the third array giving you the first element of the third array.
i.e. position 1,2 is the same as 2,0
int tester[][2]{ 1,2,3,4,5,6 } creates a 3 by 2 array.
tester[0][0] = 1
tester[0][1] = 2
tester[1][0] = 3
tester[1][1] = 4
tester[2][0] = 5
tester[2][1] = 6
The compiler creates an array using the least amount of memory possible based on your specifications. [][2] explicit says to organize the data in such a fashion that there a x rows and 2 columns. Because you put 6 elements into the tester array, the compiler decides the number of rows to assign by dividing the number of total elements by the number of columns.
Furthermore, (*(tester + 1))[2], is equivalent to tester[2], which would access the element in the first column of the third row. Thus returning 5.
It is another way to write this code which means you define vector but it acts like 2-dimensional array.
int main() {
int tester[3][2]{ {1,2},{3,4},{5,6} };
std::cout<< tester[1][2] <<std::endl;
return 0;
}

Size of an 2dim array

When I have something like this:
int Numbers[] =
{
1,
2,
3,
}
I can simply get size of this array 'int numNumbers = ARRAYSIZE(Numbers);'
And my question is... Will this work for array like this:
int Numbers[][2] =
{
{ 1,2 },
{ 3,4 },
{ 5,6 },
}
I found this definition of ARRAYSIZE:
#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
This definitely works for both single and two dimensional arrays. sizeof(a) is size of array a i.e. (number of elements in array) * (size of an element) where sizeof (*a) is size of an element.
Similarly for two dimensional case, sizeof(a) is number of elements in complete array and sizeof(*a) means size of array in one of its dimension.
Assuming ARRAYSIZE is something like:
#define ARRAYSIZE(a) (sizeof(a)/sizeof((a)[0]))
Then yes, it will, because in the second case a[0] is the same as "array of 2 integers", so sizeof(a[0]) will evaluate to sizeof(int)*2.
ARRAYSIZE() will always work with arrays of arbitrary dimension, just be careful not to use it inside a function where the array was passed as an argument, since you will not have a real array anymore in that case.

How does an index increment work in c++

My tutor told me to use an index to keep track of which character in the line the program is at. How does an index work exactly? I know its similar to count but other than that I am not sure.
At a high level, an index works on a collection. It simply says "I want the nth element of that collection" (where n is your index).
So if you have:
int foo[] = {2, 3, 5, 8, 13}; // array of 5 integers
Using 0 as the index will give you 2, using 1 will give you 3, using 2 will give you 5, using 3 will give you 8 and using 4 will give you 13.
All these are constant indices, so they will always give you the same result. However, if you use a variable as an index, that means you can retrieve a varying element from your collection.
In the case of an array, that collection is simply a block of contiguous memory. The array itself is a memory address, and by adding the index to that memory address, you find the element you're looking for.
By index he just means a pointer to the specific character. This can simply be an integer keeping track of the characters position or an actual pointer type.
string test = "Hello";
const int sLength = 5;
int index = 0;
for ( ; index < sLength ; index++ )
{
cout << "Character at index " << index << " = " << test[index];
}
In the beginning, it helped me to think of indexes as bookmarks. The bookmark keeps track of the last thing at which I was looking.
However, to really understand indexes, you should investigate pointers. You need to understand how structures are stored in memory, what addresses are, and how to sanely move from one address to another.