Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array by reference length in C++ [duplicate]

Tags:

c++

arrays

Possible Duplicate: Calculating size of an array

This question has been asked before, but I want to confirm it. Let's say I have the following C++ function:

#include <stdio.h>
#include <stdin.h>
#define length(a) sizeof(a)/sizeof(a[0])

int main()
{
    double c[] = {1.0, 2.0, 3.0};
    printf("%d\n", getLength(c));
    return 0;
}

int getLength(double c[]) { return length(c);}

This should return the wrong value because size of will return the size of the pointer as opposed to the size of the array being pointed at. This:

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

I know it works directly, but I want to know if I can somehow call it indirectly i.e. via a helper function. I understand that two possible alternatives are to either store the length of the array in a separate slot or use a vector, but what I want to know is:

Given a function getLength:

getLength(double arr[])
{
...
}

Is there a way to compute the length of arr without passing any more information?

like image 480
BlackJack Avatar asked Feb 24 '23 17:02

BlackJack


2 Answers

The question boils down to the difference between compile-time information and run-time information.

The template works because the size of the array is known at compile time, and the template is evaluated at compile time.

The other function doesn't work, because all that's known at compile time is that the function will be called with an array. The size of the array isn't specified in the function prototype. There's no run-time information passed about the size of the array either, unless you add another parameter and pass it explicitly.

like image 121
Mark Ransom Avatar answered Mar 02 '23 16:03

Mark Ransom


The template version would work. Who said it will not work?

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

This is correct. It will return the length of the array. You just need to call this function directly. It seems you want to call this function from getLength(). Don't do that, because the way you've written getLength function is equivalent to this:

int getLength(double *c) { return length(c);}

There is absolutely no difference between your written getLength() and the above version. That is, once you call this function, (or your function), the array is already decayed into a pointer to double. You've already lost the size information with the decay of the array (which is why this is called decaying of array). So you should NOT call this function, instead call the length() function directly..

However, there is little problem with length() as well. You cannot use this function where const-expression is needed, as such:

int anotherArray[length(c) * 10]; //error

So the solution would be this:

template < std::size_t N >
struct value2type { typedef char type[N]; };

template < typename T, std::size_t size >
typename value2type<size>::type& sizeof_array_helper(T(&)[size]);

#define length(a) sizeof(sizeof_array_helper(a))

Now you can write:

int anotherArray[length(c) * 10]; //ok
like image 35
Nawaz Avatar answered Mar 02 '23 16:03

Nawaz