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::array
s 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
Why Don't C++ Compilers Define Operator== and Operator!=
Heterogeneous Containers in C++
Using Strtok With a Std::String
C++ Custom Stream Manipulator That Changes Next Item on Stream
What Are the Advantages of Using Nullptr
Convert Cstring to Const Char*
Why Can Lambdas Be Better Optimized by the Compiler Than Plain Functions
How to Print Utf-8 from C++ Console Application on Windows
Throwing Exceptions from Constructors
What Kind of Optimization Does Const Offer in C/C++
How to Emulate Template≪Auto X≫
Is There a _Class_ Macro in C++
How to Check If Given C++ String or Char* Contains Only Digits