0

When you pass an array in C++, they get passed as a pointer. So we have to pass the size of that array explicitly.

// This will not work.
int GetSize(int* arr){
  return sizeof(arr)/size(int);
}

But if we don't use a function to get its size and use "sizeof" in the same function where the array was initialized, now we get the correct result.

int main(){
  int arr[5];
  int size = sizeof(arr)/sizeof(int);
  cout << size << endl;
}

So is it adequate for me to look at the array as a class with a pointer, its size and type of elements in it?

Now that I think about it, I'm not sure how C++ knows array's size in the latter code if it's just handled the same as a pointer.

7
  • 1
    When you have a "proper" array the compiler knows it, as it must keep track of all variables and their types. When you have a pointer, the compiler can't know where the pointer comes from or what it points to, as it can be decided at run-time. Commented Feb 19, 2020 at 18:13
  • 1
    Advice: Don't use C-style arrays. Use std::array or std::vector instead. Commented Feb 19, 2020 at 18:16
  • It's important to understand that pointers and arrays are unrelated and different types. The perceived connection comes from the ability that arrays have to convert very easily to pointers to their first element. Knowing where an array starts is not enough to know where it ends. Commented Feb 19, 2020 at 18:18
  • int size = sizeof(arr)/sizeof(int); --> const auto size = std::size(arr); Commented Feb 19, 2020 at 18:18
  • 2
    "So is it adequate for me to look at the array as a class with a pointer, its size and type of elements in it?" Simple answer: Absolutely not! A pointer is a pointer and not an array. And there is nothing within an pointer to an array which keeps any additional information. That any array converts while using as function parameter automatically to a pointer to the first element is simply convention. If you want have it as a template instance type which keeps size information in the type ( not the instance ) use an std::array. If you want runtime size info, use std::vector Commented Feb 19, 2020 at 18:25

4 Answers 4

2

So is it adequate for me to look at the array as a class with a pointer, its size and type of elements in it?

No, because it is not. A C-style array is just a chunk of contiguous memory holding elements of a given type, nothing more, nothing less.

Now that I think about it, I'm not sure how C++ knows array's size in the latter code if it's just handled the same as a pointer.

That is not how arrays are handled.

In your first example, the function only accepts a pointer, it doesn't care where that pointer comes from. Passing in an array will decay the array into a pointer to the 1st element. All size information is lost, and the size of the array can't be determined from the pointer alone. That is why sizeof(arr) doesn't work in that context. It only knows the size of the pointer itself, not the size of the array that the pointer came from.

In your second example, the actual array is in scope where sizeof() is being used. The compiler knows the declaration of the array, so sizeof(arr) can know the actual byte size of the array.

If you really want to know the size of a passed array in a function, and don't want to pass the size explicitly as a parameter, then pass the array by reference instead of by pointer so the array's size is not lost:

template<size_t N>
int GetSize(int (&arr)[N]){
  return N;
}
Sign up to request clarification or add additional context in comments.

Comments

0

In first case as I understand correctly, you're taking the size of a int* type which is a pointer to int and in most cases it will result in 4 bytes (depending on architecture and probably other factors).

In the second case, compiler also have all the information necessary to compute sizeof(arr) as there are explicitly given 5 elements of int as defined by int arr[5]; and as a result in most cases will equal 4 bytes * 5 elements, 20 bytes

Comments

0

The declaration

int *arr; // arr = ptr to int

is different than the declaration

int arr[5];  // arr = base ptr to array of 5 ints

Note the arr resolves to an address (ptr) in each case, but in the second case the compiler can resolve that arr is a base ptr to an array of 5 int's. Things get a little trickier if the second declaration is for a function parameter:

void foo(int arr[5]) { ... }

then this is really no different than

void foo(int *arr) { ... }
void foo(int arr[]) { ... }

i.e., only a ptr is passed and sizeof(arr) will return the number of bytes in a ptr.

8 Comments

Arrays are not pointers. int arr[5]; is an array not a pointer
Do I remember correctly, to finish your thought, unless it's for example void foo(int (&arr)[5]), then it can be resolved and it's not equal to the above int *arr and arr[]?
@cplusogl there you are declaring arr is a reference to an array of 5 int's and yes the number of elements can be resolved statically.
@idclev463035818 you are correct, but under the hood the symbol arr still resolves to an address.
Under the hood an array is still an array not a pointer. Arrays decay to pointers under certain circumstances, but that still doesnt make them pointers
|
0
  1. Why sizeof() when in the same scope? - It's because the compiler sees that you have declared int arr[5], it gets that the size is 5 at the compile time. sizeof() is computed at compile time.
  2. Why it doesn't work when array is passed as a pointer? - It's because an array decays into a pointer here. Hence, it loses the information of size. Infact, sizeof(arr) here will give you the size of a pointer on your system - 8 bytes for 64-bit machine, 4-byte for 32-bit machine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.