1

I'm trying to get the length of an array passed as a parameter on some function. The code is look like this :

double getAverage(int numbers[])
{
    int length = sizeof(numbers)/sizeof(numbers[0]);
    // here the result of the length is 1.
    int sum = 0;
    for (int i = 0 ; i < length ; i++)
    {
        sum += numbers[i];
    }
    return (double)sum / length;
}

int main()
{
    int numbers[8] = {1,2,3,4,5,6,7,8};
    //if I call here sizeof(numbers)/sizeof(numbers[0] the result will be 8 as it   
    //should be.
    cout << getAverage(numbers) << endl;
    return 0;
}

My question is how to get the array length which is passed as argument of a function by reference(although I know that every array is passed by reference)? I know that there is a lot of questions about finding the array length in C/C++ but no one of them give me the answer which I'm looking for. Thanks in advance.

4
  • 2
    It might pay to check out std::vector<T> or std::array<T, N>. Commented Jan 30, 2012 at 9:48
  • possible duplicate of How do I use arrays in C++? Commented Jan 30, 2012 at 10:01
  • Now you probably start understanding the problem with the sizeof(x)/sizeof(x[0]) approach... There are type safe alternatives in C++ (beyond using vector) to obtain the size of an array that would have detected your error at compile time. Commented Jan 30, 2012 at 13:10
  • possible duplicate of Size of an Array.... in C/C++? Commented Jan 30, 2012 at 13:13

9 Answers 9

6

You will have to explicitly pass the length of the array as an parameter to the function.

What you pass to the function is just an pointer to the array, not the array itself, so there is no way to determine the length of the array inside the function unless you explicitly pass the length as an function parameter.

You can probably use std::vector, which provides member functions to get no of elements in the vector, using std::vector::size(), that is the best you can do there is no way to do so using c-style arrays.

Sign up to request clarification or add additional context in comments.

4 Comments

yes I know but this is not the way which I'm looking for. Something like in Java. just declare an array and get it length : int[] arr = new int[5]; arr.length;
@JordanBorisov: if you are looking for an answer like "int length = numbers.len()" then i have bad news for you. The only way to get such thing is to code an Array class yourself, or use a similar existing solution. Or another language.
@JordanBorisov: My answer summarizes it.There is no way you can do so using c-style arrays.Your best can be using std::vector.
@Als: Having a reference parameter and deducing the size of the array by template argument deduction will do the job.
4

Arrays decay to pointers when passing them as parameters. You can't retrieve size information inside the function.

Why aren't you using std::vector? It's the c++ way.

1 Comment

I suppose I have to use the verctor
3

At run-time, there is no information associated with an array that tells you its length. The array pretty much "decays" into just the address of the first element.

At compile-time, the length is part of the type, so if you declare your function to take e.g. int numbers[8] you can get the length using the sizeof expression you mention.

Of course, this means you can only validly call the function with arrays of length 8, which kind of makes it a bit useless.

Thus, the only way around this is to explicitly add information at run-time about the array's length, by adding a second size_t length argument to the function.

In C++, you could also use templates to have the compiler create specialized versions of the function for each array length, but that is kind of wasteful.

As pointed out by others, you can also "level up" your abstraction and use e.g. std::vector<int> to get a size() method. That is of course pretty much the same thing, the vector container adds run-time information about the number of elements.

This might not be "the answer which you're looking for", I'm sorry about that.

Comments

2

If you must use an array, you could 'templatize' your function:

template <size_t length> double getAverage(int (&numbers)[length]) {
    int sum = 0;
    for (int i = 0 ; i < length ; i++)
    {
        sum += numbers[i];
    }
    return (double)sum / length;
} 

3 Comments

What's the purpose of the length variable when you already have the N constant?
You could simply rename N to length then :)
Note that if the function is large, it might be worth implementing it as a function that takes the length as argument (or that takes teo iteratorstyle pointers) and then a template (wrapper or helper) to obtain the size (or pointers), as that will reduce the generated code size.
1

You have to pass in the length as a parameter, or use std::vector which "contains" the length. You can access it with the size() method.

Comments

1

Or use std::vector (instead of int[]) which provides a size() function

Comments

1

You can use std::vector, or std::list as all have give. But if you are adamant that you want to use an int[] without a second argument, then you can insert a code number as the last element of the array. that way you can know the end.... Or u can save the length of the array in its first element and use the rest normally.

1 Comment

This is sound to me like some kind of processing data protocol. I like it
1

You can pass an array by reference in which case the areay size has to be specified. However, the size of a statically sized array can be deduced for a template argument:

template <int Size>
double getAverage(int (&numbers)[Size]) { ... }

The only problem with this approach is that it creates a new instantiation for each array size. Of course, the fix to this is to actually pass begin and end iterators to the function doing the actual work. The iterators can easily be determined using begin() and end() functions using the trick above. The code would look something like this:

double average
    = std::accumulate(begin(numbers), end(numbers), 0.0)
    / std::distance(begin(numbers), end(numbers));

3 Comments

+1 Note that while the accumulate/distance code might look as iterating over the array twice, tha distance of two pointers is a constant expression.
Well, it is a constant time expression: a constant expression is a compile-time thing in C++ and this it is probably not, although it could be. The main reason to use this formulation is that actually works for any non-empty container although e.g. for a list it would iterate twice over the list. The latter is a goid reason why it would be good to have versions of the algorithms taking ranges.
Right, that's the problem with writing with on a phone :) I meant constant-time expression.
0

You can use templates:

template<std::size_t Length>
double getAverage(int (&numbers)[Length])
{
...
}

but this may lead to code bloat as the compiler will create this for every new array size you pass in. You might be better off combining a template with a parameter

template<typename T, std::size_t Length>
std::size_t GetCount(T (&numbers)[Length])
{
    return Length;
}

[main]

getAverage(numbers, GetCount(numbers));

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.