I had the online coding interview today and I really struggled while trying to calculate the size of the array.
Could you please help me with how can I measure the sizeof array here? I tried my best but no luck please help here.
#include<iostream>
#include<map>
#include<vector>
using namespace std;
void arraysize(int* a) {
cout << "size1: "<<sizeof(a) << endl;
cout << "size2: " << sizeof(a[0]) << endl;;
}
int main()
{
int array1[] = { 1,2,3,4,5,6,7,8 };
arraysize(array1);
return 0;
}
Result:
size1: 4
size2: 4
In most cases, when you pass an array to a function, the array will be converted to a pointer. This is called an array-to-pointer decay. Once this decay happens, you lose the size information of the array. That is, you can no longer tell the size of the original array from the pointer.
However, one case in which this conversion / decay will not happen is when we pass a reference to the array. We can take advantage of this property to get the size of an array.
#include<iostream>
template<typename T, size_t N>
size_t asize(T (&array)[N])
{
return N;
}
int main()
{
int array1[] = { 1,2,3,4,5,6,7,8 };
std::cout << asize(array1) << std::endl; // 8
return 0;
}
In the above case, to the template function asize, we pass a reference to an array of type T[N], whose size is N. In this case, it is array type int[8]. So the function returns N, which is size 8.
C style array's decay to pointer's when passed to a function like this.
The first cout statement is printing the size of a pointer on your machine.
The second cout statement is printing the size of an integer.
Use one of the following solutions in order to pass the size of the array to the function.
template<std::size_t N>
void ArraySize( int ( &array )[ N ] )
{
std::cout << "Array size: " << N << '\n';
}
void ArraySize( int* array, std::size_t size )
{
std::cout << "Array size: " << size << '\n';
}
template<std::size_t N>
void ArraySize( std::array<int, N>& array )
{
std::cout << "Array size: "<< array.size( ) << '\n';
}
sizeof(a) returns the number of bytes in array,
sizeof(int) returns the number of bytes in an int,
ergo
sizeof(a)/sizeof(int) returns the array length
Easiest way to get the size of an array:
#include <iostream>
using namespace std;
int main(void) {
int ch[5], size;
size = sizeof(ch) / sizeof(ch[0]);
cout << size;
return 0;
}
Output: 5
simply divide sizeof(array1) by sizeof(int). it will give you total element in array. because sizeof(array1) will give total bytes in the array. for example sizeof(array1) = int * 8 because your array is int so int is 4 byte answer is 4*8 = 32.Now you have to divide it again by 4 cause its in byte.
cout << "Size of the Array is : " << sizeof(array1)/sizeof(int) << endl;
put above code in your main function to get result
Related
I'm simply trying to get the size of an array passed as a parameter in a function, but I dont understand why the sizeof(k)/sizeof(k[0]) just returns one, when it works fine in the scope where it was declared, what am i missing here?
Heres the code:
#include <iostream>
using namespace std;
int fn(int k[]){
cout << "size in function :" << sizeof(*k) / sizeof(k[0]) << endl; //returns 1 for some reason
//cout << "size in function :" << end(k)-begin(k) << endl; // can't find begin-end fitting function?
int m = *max(&k[0], &k[sizeof(k)/sizeof(int)]);
return m;
}
int main()
{
int k[] = { 1,2,3,4,5,6,7 };
int s = size(k);
cout << "size :" << sizeof(k) / sizeof(k[0]) << endl;
cout << "max: " << fn(k);
return 0;
}
The size of an array only "exists" at compile-time. By the time the code is compiled, arrays are nothing more than pointers.
So if you want a function to accept a sized array, then the size needs to be passed at compile-time, which means it has to be a template parameter.
template<std::size_t N>
int fn(int (&k)[N]){
cout << "size in function :" << N << endl;
cout << "size in function :" << end(k)-begin(k) << endl;
int m = *max(begin(k), end(k));
return m;
}
what am i missing here?
The type of the parameter is int* (after having been adjusted from an array of unknown bound).
sizeof(k)/sizeof(int)
You're dividing the size of a pointer with the size of an integer. That division has nothing to do with the size of the array whose element is being pointed at.
when it works fine in the scope where it was declared
That's because the type of that k isn't int*. The type of the that k is int[7].
find size of parameterized array
The type of a parameter is never an array in C++. If you declare a function parameter to be an array, then the type will be adjusted to be a pointer to element of such array.
If the type of the parameter is pointer, and if that pointer points to element of an array, then there is no general way to find out the size of the array in question.
Some arrays contain a sequence that is terminated by an element with a sentinel value. You can determine the length of such sequence by performing a linear search for the sentinel value. Null terminated strings are a common example of such sequences.
Old fashioned, C style is to pass the size of the array as separate parameter:
int fn(int k[], std::size_t size);
// usage
int k[] = { 1,2,3,4,5,6,7 };
fn(k, std::size(k));
A more modern approach is to combine the pointer and the size in a class. There is a class template for such purpose in the standard library:
int fn(std::span<int> k);
// usage
int k[] = { 1,2,3,4,5,6,7 };
fn(k);
This question already has answers here:
What is the purpose of sized array as function argument is c and c++?
(2 answers)
Closed 1 year ago.
Does defining a sized array in a function signature (as opposed to the more commonly used unsized array or pointer syntax) have any bearing at all? My compiler is ignoring it completely, as the following sample code shows (which runs, although it prints some garbage values when a smaller-sized array is passed).
#include <iostream>
using namespace std;
void printArray(int intArray[5]) {
for (int i = 0; i < 5; i++) {
cout << intArray[i] << " ";
}
cout << endl;
}
int main()
{
int array1[1] = {1}; // Smaller array size than in the function signature
cout << "\nInvocation 1\n";
printArray(array1);
int array2[4] = {1, 2, 3, 4}; // Smaller array size than in the function signature
cout << "\nInvocation 2\n";
printArray(array2);
int array3[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // Larger array size than in the function signature
cout << "\nInvocation 3\n";
printArray(array3);
return 0;
}
Does defining a sized array in a function signature (as opposed to the more commonly used unsized array or pointer syntax) have any bearing at all?
No, not the way you do it.
This would on the other hand make intArray a reference to the array you pass as an argument:
void printArray(int (&intArray)[5]) {
for (int i = 0; i < 5; i++) {
cout << intArray[i] << " ";
}
cout << endl;
}
A more generic form would be to make it a function template. This would then be instantiated once for each array size you call it with:
template<std::size_t N>
void printArray(int (&intArray)[N]) {
for (int i = 0; i < N; i++) {
cout << intArray[i] << " ";
}
cout << endl;
}
Does defining a sized array in a function signature (as opposed to the more commonly used unsized array or pointer syntax) have any bearing at all?
No, it has not, the passed array argument will always decay to a pointer to its first element, placing a size is indeed pointless from the compiler standpoint, it will ignore it, having void printArray(int intArray[5]){...}, void printArray(int intArray[]){...} or void printArray(int* intArray){...} will be basically the same.
My compiler is ignoring it completely, as the following sample code shows (which runs, although it prints some garbage values when a smaller-sized array is passed).
Which makes sense because in the loop you are accessing elements outside the bounds of the array, so the behavior is undefined.
This is how I would do it using std::array
#include <array>
#include <iostream>
template<typename type_t, std::size_t N>
void printArray(const std::array<type_t,N>& values)
{
for (const auto& value : values)
{
std::cout << value << " ";
}
std::cout << std::endl;
}
void printArray_s(const std::array<int, 5>& values)
{
for (const auto& value : values)
{
std::cout << value << " ";
}
std::cout << std::endl;
}
// helper function to avoid having to type value of N in std::array (syntactic sugar)
// used for array3
template<typename array_type, typename... args_t>
constexpr auto make_array(const args_t&&... values)
{
return std::array<array_type, sizeof...(args_t)>{ static_cast<array_type>(values)... };
}
int main()
{
// Smaller array size than in the function signature
std::array<int,1> array1{ 1 };
std::cout << "\nInvocation 1\n";
//printArray_s(array1); // <== will correctly give compiler error
// Smaller array size than in the function signature
std::array<int, 4> array2{ 1, 2, 3, 4 };
std::cout << "\nInvocation 2\n";
printArray(array2);
// Larger array size than in the function signature
auto array3 = make_array<int>(1, 2, 3, 4, 5, 6, 7, 8 );
std::cout << "\nInvocation 3\n";
printArray(array3);
return 0;
}
This question already has an answer here:
When passing an array to a function in C++, why won't sizeof() work the same as in the main function?
(1 answer)
Closed 1 year ago.
Forgive me for this possibly dumb question. Consider this:
int foo(int* arr) {
std::cout << arr << "(" << sizeof(arr) << ")";
}
int main()
{
int x[] = {0, 1, 2, 3, 4};
foo(x);
std::cout << " " << x << "(" << sizeof(x) << ")";
}
Output: 0x7c43ee9b1450(8) 0x7c43ee9b1450(20) - Same address, different size.
My understanding is that the function argument is an address specific to the first element of the array, so the size is 8 bytes, and the same should be true for the variable in main too; So how come the size of the variable outside of the function represent the whole array (4 bytes int times 5 elements = 20)? How could I possibly determine from inside the function how large an array actually is?
This is because the types are not the same inside and out side the function.
If you make sure the type is the same inside and outside the function you should get the same result.
int foo(int (&arr)[5])
{
std::cout << arr << "(" << sizeof(arr) << ")";
return 0;
}
The problem is that arrays decay into pointers at the drop of a hat. So if you pass an array to a function it will easily be converted into a pointer. That is what is happening here.
int foo(int* arr)
// ^^^^ Notice this is not an array.
// It is simply a pointer to an integer
// The array has decayed into a pointer to the
// first element in the array.
{
std::cout << arr << "(" << sizeof(arr) << ")";
return 0;
}
How could I possibly determine from inside the function how large an array actually is?
This is actually a real problem with C. In C they solved this by getting you to pass the size of the array as a second parameter:
int foo(int* arr, std::size_t size);
Then call it from main as:
foo(arr, sizeof(arr)/sizeof(arr[0])); // This always works as it done
// at compile time and not runtime
In C++ we don't usually use C-arrays but prefer std::vector or std::array as the size is easily retrievable. Generally we use a container type C as they are duck types of Container:
template<typename C>
int foo(C& container)
{
std::cout << "(" <<container.size() << ")";
return container.size();
}
When passing an array like that you loose ALL the size information.
So the called function is flying blind with regard to the array size.
In C++ is makes much more sense to use std::array (fixed size arrays), and std::vector (changing size arrays). It is much clearer what your intent is when you pass them to functions. There will be less mistakes and less memory access issues in your code.
I hope I don't scare you too much with the template version.
The vector variant is more easy, but may use a bit more memory at runtime.
#include <array>
#include <vector>
#include <iostream>
template<size_t N>
size_t foo(const std::array<int,N>& arr)
{
for (const auto n : arr) std::cout << n << " ";
std::cout << "(" << arr.size() << ")" << std::endl;
return arr.size();
}
size_t foo(const std::vector<int>& arr)
{
for (const auto n : arr) std::cout << n << " ";
std::cout << "(" << arr.size() << ")" << std::endl;
return arr.size();
}
int main()
{
std::array<int,5> x{ 0, 1, 2, 3, 4 };
std::vector<int> y{ 0, 1, 2, 3, 4 };
auto size_x = foo(x);
auto size_y = foo(y);
}
(Disclaimer: Pointers in C++ is a VERY popular topic and so I'm compelled to believe that someone before me has already raised this point. However, I wasn't able to find another reference. Please correct me and feel free to close this thread if I'm wrong.)
I've come across lots of examples that distinguish between pointer to first element of array and pointer to the array itself. Here's one program and its output:
//pointers to arrays
#include <iostream>
using namespace std;
int main() {
int arr[10] = {};
int *p_start = arr;
int (*p_whole)[10] = &arr;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
cout << "Adding 1 to both . . . " <<endl;
p_start += 1;
p_whole += 1;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
return 0;
}
Output:
p_start is 0x7ffc5b5c5470
P_whole is 0x7ffc5b5c5470
Adding 1 to both . . .
p_start is 0x7ffc5b5c5474
P_whole is 0x7ffc5b5c5498
So, as expected, adding 1 to both gives different results. But I'm at a loss to see a practical use for something like p_whole. Once I have the address of the entire array-block, which can be obtained using arr as well, what can I do with such a pointer?
For single arrays, I don't think there's much point to it. Where it becomes useful is with multi-dimensional arrays, which are arrays of arrays. A pointer to one of the sub-arrays is a pointer to the row, and incrementing it gets you a pointer to the next row. In contrast, a pointer to the first element of the inner array is a pointer to a single element, and incrementing it gets you the next element.
int (*)[10] is a "stronger" type than int* as it keeps size of the array,
so you may pass it to function without passing additional size parameter:
void display(const int(*a)[10]) // const int (&a)[10] seems better here
{
for (int e : *a) {
std::cout << " " << e;
}
}
versus
void display(const int* a, std::size_t size) // or const int* end/last
{
for (std::size_t i = 0; i != size; ++i) {
std::cout << " " << a[i];
}
}
im trying to get the sizeof char array variable in a different function where it was initialize however cant get the right sizeof. please see code below
int foo(uint8 *buffer){
cout <<"sizeof: "<< sizeof(buffer) <<endl;
}
int main()
{
uint8 txbuffer[13]={0};
uint8 uibuffer[4] = "abc";
uint8 rxbuffer[4] = "def";
uint8 l[2]="g";
int index = 1;
foo(txbuffer);
cout <<"sizeof after foo(): " <<sizeof(txbuffer) <<endl;
return 0;
}
the output is:
sizeof: 4
sizeof after foo(): 13
desired output is:
sizeof: 13
sizeof after foo(): 13
This can't be done with pointers alone. Pointers contain no information about the size of the array - they are only a memory address. Because arrays decay to pointers when passed to a function, you lose the size of the array.
One way however is to use templates:
template <typename T, size_t N>
size_t foo(const T (&buffer)[N])
{
cout << "size: " << N << endl;
return N;
}
You can then call the function like this (just like any other function):
int main()
{
char a[42];
int b[100];
short c[77];
foo(a);
foo(b);
foo(c);
}
Output:
size: 42
size: 100
size: 77
You cant. In foo you are asking for the size of a "uint8_t pointer". Pass the size as a separate parameter if you need it in foo.
Some template magic:
template<typename T, size_t size>
size_t getSize(T (& const)[ size ])
{
std::cout << "Size: " << size << "\n";
return size;
}