开发者

Array by reference length in C++ [duplicate]

This question already has answers here: Closed 11 years ago.

Possible Duplicate: Calculating size of an array

This question has been as开发者_开发知识库ked 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?


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.


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


To fix your first example, you have to do the following (length macro taken from this answer):

#include <stdlib.h>
#include <stdio.h>

#define length(a) ((sizeof(a)/sizeof(0[a])) / ((size_t)(!(sizeof(a) % sizeof(0[a])))))

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

Note that I did not call length from getLength() because that would cause a divide by zero problem.

You can replace my macro with #define length(a) (sizeof(a) / sizeof(*a)) but that will return 1 as the size, which is wrong.

Your first example, after it has been fixed (see my comment to your answer), will return a size of zero.

You are not permitted to call the templated function from your getLength() function.

The following code will fix your templated example:

#include <stdlib.h>
#include <stdio.h>
int getLength(double c[]);

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

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

    return 0;
}

so to answer your question, no you have to do it one of two ways like above. You cannot pass the array as you are doing because the array decays into a pointer. That's why pass by reference is preferred. By reference will give the proper sizeof(). See this answer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜