继 fizzer 在C++ 构造替换 C 构造的帖子之后,我将在这里写下我的答案:
警告:下面提出的 C++ 解决方案不是标准 C++,而是 g++ 和 Visual C++ 的扩展,并被提议作为 C++0x 的标准(感谢Fizzer对此的评论)
请注意,Johannes Schaub - litb 的回答提供了另一种符合 C++03 标准的方法。
问题
如何提取C数组的大小?
建议的 C 解决方案
资料来源:C++ 宏什么时候有用?
#define ARRAY_SIZE(arr) (sizeof arr / sizeof arr[0])
与当前线程中讨论的“首选”模板解决方案不同,您可以将其用作常量表达式:
char src[23];
int dest[ARRAY_SIZE(src)];
我不同意 Fizzer,因为有一个模板化解决方案能够生成常量表达式(事实上,模板的一个非常有趣的部分是它们在编译时生成常量表达式的能力)
无论如何,ARRAY_SIZE 是一个能够提取 C 数组大小的宏。我不会详细说明 C++ 中的宏:目的是找到一个相同或更好的 C++ 解决方案。
更好的 C++ 解决方案?
以下 C++ 版本没有任何宏问题,并且可以以相同的方式执行任何操作:
template <typename T, size_t size>
inline size_t array_size(T (&p)[size])
{
// return sizeof(p)/sizeof(p[0]) ;
return size ; // corrected after Konrad Rudolph's comment.
}
示范
如以下代码所示:
#include <iostream>
// C-like macro
#define ARRAY_SIZE(arr) (sizeof arr / sizeof arr[0])
// C++ replacement
template <typename T, size_t size>
inline size_t array_size(T (&p)[size])
{
// return sizeof(p)/sizeof(p[0]) ;
return size ; // corrected after Konrad Rudolph's comment.
}
int main(int argc, char **argv)
{
char src[23];
char * src2 = new char[23] ;
int dest[ARRAY_SIZE(src)];
int dest2[array_size(src)];
std::cout << "ARRAY_SIZE(src) : " << ARRAY_SIZE(src) << std::endl ;
std::cout << "array_size(src) : " << array_size(src) << std::endl ;
std::cout << "ARRAY_SIZE(src2) : " << ARRAY_SIZE(src2) << std::endl ;
// The next line won't compile
//std::cout << "array_size(src2) : " << array_size(src2) << std::endl ;
return 0;
}
这将输出:
ARRAY_SIZE(src) : 23
array_size(src) : 23
ARRAY_SIZE(src2) : 4
在上面的代码中,宏将指针误认为是数组,因此返回了错误的值(4,而不是 23)。相反,模板拒绝编译:
/main.cpp|539|error: no matching function for call to ‘array_size(char*&)’|
从而证明模板解决方案是: * 能够在编译时生成常量表达式 * 如果以错误的方式使用,能够停止编译
结论
因此,总而言之,模板的参数是:
- 没有类似宏的代码污染
- 可以隐藏在命名空间内
- 可以防止错误的类型评估(指向内存的指针不是数组)
注意:感谢 Microsoft 为 C++ 实现 strcpy_s ...我知道这有一天会为我服务... ^_^
http://msdn.microsoft.com/en-us/library/td1esda9.aspx
编辑:该解决方案是针对 C++0x 标准化的扩展
Fizzer 确实正确地评论了这在当前的 C++ 标准中是无效的,并且是完全正确的(因为我可以在 g++ 上通过 -pedantic 选项进行验证)。
尽管如此,这不仅在今天的两个主要编译器(即 Visual C++ 和 g++)上可用,而且在 C++0x 中也考虑过,正如以下草案中所提议的那样:
C++0x 的唯一变化可能是这样的:
inline template <typename T, size_t size>
constexpr size_t array_size(T (&p)[size])
{
//return sizeof(p)/sizeof(p[0]) ;
return size ; // corrected after Konrad Rudolph's comment.
}
(注意constexpr关键字)
编辑 2
Johannes Schaub - litb 的答案提供了另一种符合 C++03 的方法。我将在此处复制粘贴源代码以供参考,但请访问他的答案以获取完整示例(并对其进行升级!):
template<typename T, size_t N> char (& array_size(T(&)[N]) )[N];
用作:
int p[] = { 1, 2, 3, 4, 5, 6 };
int u[sizeof array_size(p)]; // we get the size (6) at compile time.
我大脑中的许多神经元都被炸了,以使我了解它的本质array_size
(提示:它是一个返回对 N 字符数组的引用的函数)。
:-)