When Passing an Array to a Function in C++, Why Won't Sizeof() Work the Same as in the Main Function

When passing an array to a function in C++, why won't sizeof() work the same as in the main function?

The problem is here:

int length_of_array(int some_list[]);

Basically, whenever you pass an array as the argument of a function, no matter if you pass it like int arr[] or int arr[42], the array decays to a pointer (with ONE EXCEPTION, see below), so the signature above is equivalent to

int length_of_array(int* some_list);

So of course when doing sizeof(some_list)/sizeof(*some_list) you will get the ratio between the size of the pointer the array decayed to and the size of the type representing the first element. In your case, 1, as it looks like on your machine the size of a pointer is probably 4 bytes (32 bits), same as the size of an int.

So my C++ instructor told us in class that there was no function to determine an array size in C++ and I was not satisfied with that.

YOUR TEACHER IS WRONG! There is a way of passing an array by reference and getting its size:

template<size_t N>
int length_of_array(int (&arr)[N])
{
std::cout << N << std::endl; // WORKS!
return N;
}

Why isn't the size of an array parameter the same as within main?

An array-type is implicitly converted into pointer type when you pass it in to a function.

So,

void PrintSize(int p_someArray[10]) {
printf("%zu\n", sizeof(p_someArray));
}

and

void PrintSize(int *p_someArray) {
printf("%zu\n", sizeof(p_someArray));
}

are equivalent. So what you get is the value of sizeof(int*)

Why does size of array differ in main and other function?

Because the array is decayed to a pointer What is array to pointer decay?.

you can pass the array by reference to see the same size, as follows

#include <iostream>

template <class T, size_t n> void func(T (&arr)[n]) {
std::cout << "func size: " << sizeof(arr) << "\n";
}

int main() {
int arr[5];
std::cout << sizeof(arr) << "\n";
func(arr);
}

Demo

And see Why is "using namespace std;" considered bad practice?
and Why should I not #include <bits/stdc++.h>?

How do i handle this situation C++ sizeof problem

If I have understood correctly you are trying to get the size of the passed array in the function.

Do it the following way

template <size_t N>
void f( int* ( &b )[N] )
{
cout << sizeof( b ) << endl;
}

In C you should declare the function with one more parameter like

void f(int* b[], size_t n )
{
printf( "%zu\n", n * sizeof( *b ) );
}

and call it like

f(a, sizeof( a ) / sizeof( *a ) );

Such an approach you can use also in C++.

C++: Create function that returns array size

Nice demonstration why are ordinary raw arrays dangerous.

The issue is with pointer arithmetic and +1. For T* ptr;, ptr+1 advanced the pointer by sizeof(T) bytes, or one T.

In main, &array is of type string(*)[4], so the pointer is incremented by sizeof(string)*4. This leads to the correct size.

On contrary, string array[] in arrayLength() has type string* even if you use []. The increment is only sizeof(string*) in bytes thus leading to incorrect size.

Just use std::array or std::vector with their size().

Why is the code that works correctly in Main works incorrectly inside the function ? (C++)

To rewrite the two examples

const int len1 = sizeof(int[10]) / sizeof(int)

and

const int len2 = sizeof(int*) / sizeof(int);

The first one takes the size of an int array, whereas the second one takes the size of an int pointer. In your architecture, an int is 4 bytes long, and an array of 10 ints is therefore 40 bytes long. A pointer on the other side, takes 8 bytes on this architecture (most likely 64 bit).

std::size() from iterator library won't work on C-style array passed to function

is it because of when you pass this to a function the array decay to a pointer?

Almost. More accurately, it is because you declared that the function argument is a pointer. std::size only works with containers (or anything that has member function size) and arrays. A pointer is neither of those.

Error When Passing String array to function in C++

As an alternative to the answer provided by @ACB, you can use a std::array.

#include <array>
#include <string>
#include <iostream>

template <std::size_t S>
void foo(std::array<std::string, S> &bar) {
for (auto &i : bar) {
std::cout << i << std::endl;
}
}

int main() {
std::array<std::string, 3> baz = {"hello", "world", "wooble"};

foo(baz);

return 0;
}

We could even use the template to allow for std::arrays of other types. As long as there is an applicable << overload with std::ostream and T.

#include <array>
#include <string>
#include <iostream>

template <typename T, std::size_t S>
void foo(std::array<T, S> &bar) {
for (auto &i : bar) {
std::cout << i << std::endl;
}
}

int main() {
std::array<std::string, 3> baz = {"hello", "world", "wooble"};

foo(baz);

return 0;
}


Related Topics



Leave a reply



Submit