-4

This is what I use to get the length of an array:

sizeof(counts) / sizeof(unsigned long)

Now I want to make a simple function out of it like:

int length(unsigned long* input)
{
    return (sizeof(input) / sizeof(unsigned long));
}


unsigned long array[3];

sizeof(array) = 12
sizeof(unsigned long) = 4
sizeof(array) / sizeof(unsigned long) = 3

lenght(array) = 1

Inside length() sizeof(array) returns 4

The compiler will complain when I change the function to:

int length(unsigned long input)
{
  return (sizeof(input) / sizeof(unsigned long));
}

I'm either stoned or just dumb, what am I doing wrong?

  • 2
    What you're doing wrong is not realizing that since `input` is an `unsigned long *`, then `sizeof(input)` is equivalent to `sizeof(unsigned long *)`, which is always the same value, whether this is a pointer to one, or a billion unsigned long. `sizeof` is a ***compile-time constant***, that's evaluated at compile time to the size of its argument. – Sam Varshavchik Aug 17 '18 at 00:15
  • https://msdn.microsoft.com/en-us/library/ms175773.aspx – Алексей Неудачин Aug 17 '18 at 00:20
  • ***what am I doing wrong?*** Using a c-array instead of std:array. However I assume you are in class and are not permitted to use std::array. – drescherjm Aug 17 '18 at 00:22
  • I'm not in class, been programming for quite a while but this just stumped me and I know what I've been doing wrong now :) Thanks! – Sjoer van der Ploeg Aug 17 '18 at 00:38

3 Answers3

2
template <typename T, size_t N>
size_t length(T (&input)[N])
{
    return N;
}

Or just use std::extent

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • I would mark length() function as the constexpr function. Then you can write something like this. int xyz[100]; int abc[length(xyz)]; – Timmy_A Aug 17 '18 at 00:26
1

You can't, because the array is decayed to a pointer to its first element. However, you can do something like that :

template<size_t N>
void foo(int (&array)[N]) {
    for(auto elem : array) use(elem);
}

template<typename T, size_t N>
size_t length(T (&)[N]) {
    return N;
}

Else you can use std::array that is the proper way to do static array in C++

Antoine Morrier
  • 3,930
  • 16
  • 37
1

You are neither stoned or dumb (well, unless....). The sizeof operator can only be used on an array within the scope the array was declared. When an array is passed as a parameter, it is converted to a pointer to the first element of the array.

So length receives input as unsigned long *. What is unsigned long *? (hint: a pointer). What is sizeof (a pointer) (hint: generally 4-bytes on x86 or 8-bytes on x86_64).

So while you can use sizeof(input) / sizeof(unsigned long) in the scope where input was declared as an array, e.g. unsigned long array[3];, once it is passed as a parameter -- it is simply a pointer.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • This is on Arduino, I simply forgot pointers return the size of the first element. Thanks! – Sjoer van der Ploeg Aug 17 '18 at 00:59
  • Glad to help. Just make sure you are clear that when `input` is passed in `int length(unsigned long* input)`, `input` is a pointer to the first element of `input`. It does NOT matter what type (e.g. `char, int, long`, etc...) because the `sizeof (a pointer)` will be the same for all. It is the number of bytes required to store any pointer that is returned, not the number of bytes related to the `type` of the first element. – David C. Rankin Aug 17 '18 at 07:38