之前已经问过这个问题,但我想确认一下。假设我有以下C ++函数:
#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);}
这应该返回错误的值,因为size将返回指针的大小而不是指向的数组的大小。这样:
template<typename T, int size>
int length(T(&)[size]){return size;}
我知道它可以直接使用,但我想知道我是否能以某种方式间接调用它,即通过辅助函数。我理解两种可能的替代方法是将数组的长度存储在单独的插槽中或使用向量,但我想知道的是:
给定函数getLength:
getLength(double arr[])
{
...
}
有没有办法计算arr
的长度而不传递更多信息?
答案 0 :(得分:4)
问题归结为编译时信息和运行时信息之间的区别。
模板有效,因为在编译时已知数组的大小,并且在编译时评估模板。
另一个函数不起作用,因为在编译时已知的是该函数将使用数组调用。函数原型中未指定数组的大小。除非你添加另一个参数并明确地传递它,否则没有传递关于数组大小的运行时信息。
答案 1 :(得分:3)
模板版本可行。谁说它不起作用?
template<typename T, int size>
int length(T(&)[size])
{
return size;
}
这是对的。它将返回数组的长度。 您只需要直接调用此函数。您似乎想从getLength()
调用此函数。不要这样做,因为你写getLength
函数的方式与此相同:
int getLength(double *c) { return length(c);}
您的书面getLength()
与上述版本完全没有区别。也就是说,一旦你调用了这个函数(或你的函数),数组就已经衰减成一个指针来加倍。您已经丢失了数组衰减的size
信息(这就是为什么这称为decaying of array
)。所以你不应该调用这个函数,而是直接调用length()
函数..
但是,length()
也没有什么问题。您不能在需要const-expression的地方使用此函数,因此:
int anotherArray[length(c) * 10]; //error
所以解决方案就是:
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))
现在你可以写:
int anotherArray[length(c) * 10]; //ok
答案 2 :(得分:1)
要修复您的第一个示例,您必须执行以下操作(从此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;
}
请注意,我没有从getLength()调用length,因为这会导致除零问题。
你可以用#define length(a) (sizeof(a) / sizeof(*a))
替换我的宏,但是会返回1作为大小,这是错误的。
您的第一个示例在修复后(请参阅我对您的回答的评论)将返回零大小。
您不能通过getLength()
功能调用模板化功能。
以下代码将修复您的模板示例:
#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;
}
所以要回答你的问题,不,你必须采取上述两种方式之一。您无法正常传递数组,因为数组会衰减为指针。这就是为什么通过引用是优选的。通过引用将给出正确的sizeof()。请参阅此answer。