How do sizeof(arr) / sizeof(arr[0]) work? - c++

When looking for a size of an array in a for loop I've seen people write
int arr[10];
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){}
How is sizeof(arr) / sizeof(arr[0]) the length of the array? How does it technically work?

If you have an array then sizeof(array) returns the number of bytes the array occupies. Since each element can take more than 1 byte of space, you have to divide the result with the size of one element (sizeof(array[0])). This gives you number of elements in the array.
Example:
std::uint32_t array[10];
auto sizeOfInt = sizeof(std::uint32_t); // 4
auto numOfBytes = sizeof(array); // 10*sizeOfInt = 40
auto sizeOfElement = sizeof(array[0]); // sizeOfInt = 4
auto numOfElements = sizeof(array) / sizeof(array[0]); // numOfBytes / sizeOfElement = 40 / 4 = 10
LIVE EXAMPLE
Note that if you pass an array to a function, the above won't work since the array decays to a pointer and sizeof(array) returns the size of the pointer.
std::size_t function(std::uint32_t a[]) // same for void function(std::uint32_t a[10])
{
return sizeof(a); // sizeof(std::uint32_t*)!
}
std::uint32_t array[10];
auto sizeOfArray = function(array); // array decays to a pointer inside function()
LIVE EXAMPLE #2

As it is described in the C++ Standard (5.3.3 Sizeof)
1 The sizeof operator yields the number of bytes in the object
representation of its operand. The operand is either an expression,
which is an unevaluated operand (Clause 5), or a parenthesized
type-id.
In this expression
sizeof(arr) / sizeof(arr[0])
there are used two subexpressions with the sizeof operator.
This subexpression
sizeof(arr)
yields the number of bytes occupied by array arr (I suppose that arr is an array).
For example if you declared an array like
int arr[10];
then the compiler has to reserve memory that to hold 10 elements of type int. If for example sizeof( int ) is equal to 4 then the compiler will reserve 10 * 4 = 40 bytes of memory.
Subexpression
sizeof(arr[0])
gives the number of bytes occupied by one element in the array. You could use any index as for example
sizeof(arr[1000])
because the expression is unevaluated. It is only important the size in bytes of the object (an element of the array) used inside the operator.
Thus if you know the total bytes that were reserved for an array
sizeof(arr)
and know how many bytes each element of the array occupies (all elements of an array have the same size) then you can calculate the number of elements in the array by using the formula
sizeof(arr) / sizeof(arr[0])
Here is a simple relation. If you have an array of N elements of type T
T arr[N];
and you know the size of the memory occupied by the array then you can calculate the size of its element by using formula
sizeof( arr ) / N == size of an element of the array.
And vice verse
If you know the size of the memory occupied by the array and the size of its element you can calculate the number of elements in the array
sizeof( arr ) / sizeof( a[0] ) == N - number of elements in the array
The last expression you can rewrite also the following way
sizeof( arr ) / sizeof( T ) == N - number of elements in the array
because the elements of the array have type T and each element of the array occupies exactly the number of bytes that are required to allocate an object of type T.
Take into acccount that usually beginners make such an error. They pass an array as an argument to a function. For example let's assume that you have a function
void f( int a[] )
{
// ...
}
And you pass to the function your array
int arr[10];
f(arr);
then the function uses the pointer to the first element of the array. In fact the function has declaration
void f( int *a )
{
// ...
}
So if you write for example within the function
void f( int *a )
{
size_t n = sizeof( a ) / sizeof( a[0] );
// ...
}
then as a within the function is a pointer (it is not an array) then you will get something like
void f( int *a )
{
size_t n = sizeof( int * ) / sizeof( int );
// ...
}
Usually the size of a pointer equal to either 8 or 4 bytes depending of the used environment. And you won't get the number of elements. You will get some weird value.

int - is equal to 4 bytes
sizeof(int) it means: 1 * 4 = 4
int arr[10] - is holding 10 int
sizeof(arr) it means: 10 * 4 = 40, we got 10 int and every int got 4 bytes,, arr without the [] it means all the arr.
sizeof(arr[0]) it means: 1 * 4 = 4
sizeof(arr) / sizeof(arr[0]) = 10*4 / 1*4 = 10,, and it is the length of the array.

It only works if arr has not been decayed into a pointer, that is, it is an array type, not a pointer type.
sizeof(arr) is the total size occupied by the array.
sizeof(arr[0]) is the size of the first element in the array. (Note that zero length arrays are not permitted in C++ so this element always exists if the array itself exists).
Since all the elements will be of the same size, the number of elements is sizeof(arr) / sizeof(arr[0]).

When dealing with an array (some_type name[some_size]) sizeof(name) is how many bytes the array occupies. Dividing the total size of the array by the size of one element (sizeof(name[0])) gives you how many elements are in the array.

c++ way to use extent, which allows u to get a number of elements in Nth dimension of the array.
see http://en.cppreference.com/w/cpp/types/extent for details
int values[] = { 1 };
std::extent<decltype(values)>::value == 1

Let's take an example like the arr[]={1,2,4,3,5}.
Then the size of the array will be 5 and the size of arr[0] will be "1" BECAUSE it consists of an element in it. Basically it's a subarray the from the above problem it will be 5/1 it will automatically returns the size of array =5.

The difference is
int arr[5] = {1,2,3,4,5};
here arr is Pointer to array and &arr[0] is pointer of type Integer

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';
}

How are 2-Dimensional Arrays stored in memory?

#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[101][101];
a[2][0]=10;
cout<<a+2<<endl;
cout<<*(a+2)<<endl;
cout<<*(*(a+2));
return 0;
}
Why are the values of a+2 and *(a+2) same? Thanks in advance!
a is a 2D array, that means an array of arrays. But it decays to a pointer to an array when used in appropriate context. So:
in a+2, a decays to a pointer to int arrays of size 101. When you pass is to an ostream, you get the address of the first element of this array, that is &(a[2][0])
in *(a+2) is by definition a[2]: it is an array of size 101 that starts at a[2][0]. It decays to a pointer to int, and when you pass it to an ostream you get the address of its first element, that is still &(a[2][0])
**(a+2) is by definition a[2][0]. When you pass it to an ostream you get its int value, here 10.
But beware: a + 2 and a[2] are both pointers to the same address (static_cast<void *>(a+2) is the same as static_cast<void *>(a[2])), but they are pointers to different types: first points to int array of size 101, latter to int.
I'll try to explain you how the memory is mapped by the compiler:
Let's consider a more pratical example multi-dimentional array:
int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
You can execute the command
x/10w a
In GDB and look at the memory:
0x7fffffffe750: 1 2 3 4
0x7fffffffe760: 5 6 7 8
0x7fffffffe770: 9 0
Each element is stored in a int type (32 bit / 4 bytes).
So the first element of the matrix has been stored in:
1) a[0][0] -> 0x7fffffffe750
2) a[0][1] -> 0x7fffffffe754
3) a[0][2] -> 0x7fffffffe758
4) a[1][0] -> 0x7fffffffe75c
5) a[1][1] -> 0x7fffffffe760
6) a[1][2] -> 0x7fffffffe764
7) a[2][0] -> 0x7fffffffe768
...
The command:
std::cout << a + 2 << '\n'
It will print the address 0x7fffffffe768 because of the
pointer aritmetic:
Type of a is int** so it's a pointer to pointers.
a+2 is the a[0] (the first row) + 2. The result is a pointer
to the third row.
*(a+2) deferences the third row, that's {7,8,9}
The third row is an array of int, that's a pointer to int.
Then the operator<< will print the value of that pointer.
A 2-dimensional array is an array of arrays, so it's stored like this in memory:
char v[2][3] = {{1,3,5},{5,10,2}};
Content: | 1 | 3 | 5 | 5 | 10 | 2
Address: v v+1 v+2 v+3 v+4 v+5
To access v[x][y], the compiler rewrites it as: *(v + y * M + x) (where M is the second dimension specified)
For example, to access v[1][1], the compiler rewrites it as *(v + 1*3 + 1) => *(v + 4)
Be aware that this is not the same as a pointer to a pointer (char**).
A pointer to a pointer is not an array: it contains and address to a memory cell, which contains another address.
To access a member of a 2-dimensional array using a pointer to a pointer, this is what is done:
char **p;
/* Initialize it */
char c = p[3][5];
Go to the address specified by the content of p;
Add the offset to that address (3 in our case);
Go to that address and get its content (our new address).
Add the second offset to that new address (5 in our case).
Get the content of that address.
While to access the member via a traditional 2-dimensional array, these are the steps:
char p[10][10];
char c = p[3][5];
Get the address of pand sum the first offset (3), multiplied by the dimension of a row (10).
Add the the second offset (5) to the result.
Get the content of that address.
If you have an array like this
T a[N];
then the name of the array is implicitly converted to pointer to its first element with rare exceptions (as for example using an array name in the sizeof operator).
So for example in expression ( a + 2 ) a is converted type T * with value &a[0].
Relative to your example wuth array
int a[101][101];
in expression
a + 2
a is converted to rvalue of type int ( * )[101] and points to the first "row" of the array. a + 2 points to the third "row" of the array. The type of the row is int[101]
Expression *(a+2) gives this third row that has type int[101] that is an array. And this array as it is used in an expression in turn is converted to pointer to its first element of type int *.
It is the same starting address of the memory area occupied by the third row.
Only expression ( a + 2 ) has type int ( * )[101] while expression *( a + 2 ) has type int *. But the both yield the same value - starting address of the memory area occupied by the third row of the array a.
The first element of an array is at the same location as the array itself - there is no "empty space" in an array.
In cout << a + 2, a is implicitly converted into a pointer to its first element, &a[0], and a + 2 is the location of a's third element, &a[2].
In cout << *(a + 2), the array *(a + 2) - that is, a[2] - is converted into a pointer to its first element, &a[2][0].
Since the location of the third element of a and the location of the first element of the third element of a are the same, the output is the same.

Strange behavior of C++ array size

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

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.

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.