simple call by reference
void foo(int* A)
{
// ...
}
void main()
{
int A[] = {1,1,1,1,1,1,1,1,1};
foo(A);
}
not sure why but it is lessening the size of the array and losing/leaking information on the array....
simple call by reference
void foo(int* A)
{
// ...
}
void main()
{
int A[] = {1,1,1,1,1,1,1,1,1};
foo(A);
}
not sure why but it is lessening the size of the array and losing/leaking information on the array....
You're passing a pointer to the first element of an array. Create your function with the prototype
void foo(int* A, int size);
You will still be able to access A[0...size-1] like normal.
not sure why but it is lessening the size of the array and losing/leaking information on the array....
In foo()
, sizeof(A) == 8
not because it is "leaking" information, but because 8 is the size of the pointer of type int*
. This is true regardless of how many integers A
was initialized with in main()
.
This may shine some light on what is happening:
#include<iostream>
using namespace std;
void foo(int* A)
{
cout << "foo: " << sizeof(A) << endl; // 8
}
void bar(int A[])
{
cout << "bar: " << sizeof(A) << endl; // still 8
}
int main()
{
int A[] = {1,1,1,1,1,1,1,1,1};
cout << "main: " << sizeof(A) << endl; // 36 (=4*9)
foo(A);
bar(A);
return 0;
}
Output:
main: 36
foo: 8
bar: 8
In main
, sizeof
"knows" the size of A[]
- it is sizeof(int) * length = 4 * 9 = 36. This information is lost when A[]
is cast to a pointer A*
in foo
.
What if we pass in A
as bar(int A[])
instead. Will that retain the array length? No! In that case, sizeof(A)
is still 8, the size of the pointer. Only in main
does the compiler retain the information of array size of A
.
If you want your functions to know the size of the array, use the std::vector<int>
template, or pass in the size separately.
Here's another discussion on this: When a function has a specific-size array parameter, why is it replaced with a pointer?
You should totally drop C-style arrays and use std::array
instead. Just compare this (which is the solution to your problem):
void foo(int* A, std::size_t size) {
// ...
}
int main() {
int A[] = {1,1,1,1,1,1,1,1,1};
foo(A, (sizeof(A) / sizeof(int)));
}
to:
template<std::size_t Size>
void foo(const std::array<int, Size>& array) {
// ...
}
int main() {
std::array<int, 9> A {{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }};
foo(A);
}
Ain't it beautiful? Or just take a look at how gorgeous it is with std::vector
:
void foo(const std::vector<int>& vector) {
// vector.size() is the size
}
int main() {
std::vector<int> A = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
foo(A);
}
And if you really want foo
to be a generic algorithm, I'll just blow your mind with iterators:
template<class Iterator>
void foo(Iterator begin, Iterator end) {
// ...
}
int main() {
std::array<int, 9> A {{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }};
std::vector<int> B = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
foo(A.begin(), A.end()); // not a single problem
foo(B.begin(), B.end()); // was given that day
}
C++ has an amazing (arguably) standard library and an amazing type system (if you don't overlook C legacy "features", like void*
): use them.
The correct way to pass array by reference is
void foo(int (&A) [9])
{
// sizeof(A) == sizeof(int) * 9
}
the generic way is so:
template <std::size_t N>
void foo(int (&A) [N])
{
// sizeof(A) == sizeof(int) * N
}
You may use std::array
(C++11 required) which has a syntax more intuitive
template <std::size_t N>
void foo(std::array<int, N> &A)
{
// A.size() == N
}