How Would You Get the Count of an Array in C++?
来源:互联网 发布:北京租房 知乎 编辑:程序博客网 时间:2024/05/29 17:10
The question is simple: given a C++ array (e.g. x as in int x[10]), how would you getthe number of elements in it?
An obvious solution is the following macro (definition 1):
#define countof( array ) ( sizeof( array )/sizeof( array[0] ) )
I cannot say this isn’t correct, because it does give theright answer when you give it an array. However, the same expression gives you something bogus when you supplysomething that is not an array. Forexample, if you have
int * p;
then countof( p ) always give you 1 on a machine where an int pointer and an int havethe same size (e.g. on a Win32 platform).
This macro also wrongfully accepts any object of a classthat has a member function operator[]. For example, suppose you write
class IntArray
{
private:
int * p;
size_t size;
public:
int & operator [] ( size_t i );
} x;
then sizeof( x ) will be the size of the x object, not thesize of the buffer pointed to by x.p. Therefore you won’t get a correct answer by countof( x ).
So we conclude thatdefinition 1 is not good because the compiler does not prevent you frommisusing it. It fails to enforce thatonly an array can be passed in.
What is a better option?
Well, if we want the compilerto ensure that the parameter to countof is always an array, we have to find a context where only an array is allowed. The same context should reject any non-arrayexpression.
Some beginners may try this (definition 2):
template <typename T, size_tN>
size_t countof( T array[N] )
{
return N;
}
They figure, this templatefunction will accept an array of Nelements and return N.
Unfortunately, this doesn’tcompile because C++ treats an arrayparameter the same as a pointer parameter, i.e. the above definition isequivalent to:
template <typename T, size_tN>
size_t countof( T * array )
{
return N;
}
It now becomes obvious thatthe function body has no way of knowing what N is.
However, if a functionexpects an array reference, then thecompiler does make sure that the size of the actual parameter matches thedeclaration. This means we can makedefinition 2 work with a minor modification (definition 3):
template <typename T, size_tN>
size_t countof( T (&array)[N] )
{
return N;
}
This countof works very well and youcannot fool it by giving it a pointer. However, it is a function, nota macro. This means you cannot use it where a compile time constant is expected. In particular, you cannot write something like:
int x[10];
int y[ 2*countof(x) ]; // twice as big asx
Can we do anything about it?
Someone (I don’t know who itis – I just saw it in a piece of code from an unknown author) came up with aclever idea: moving N from the body of thefunction to the return type (e.g. make the function return an array ofN elements), then we can getthe value of N without actually calling the function.
To be precise, we have tomake the function return an arrayreference, as C++ does not allow you to return an array directly.
The implementation of thisis:
template <typename T, size_tN>
char ( &_ArraySizeHelper( T (&array)[N] ))[N];
#define countof( array ) (sizeof( _ArraySizeHelper( array ) ))
Admittedly, the syntax looksawful. Indeed, some explanation isnecessary.
First, the top-level stuff
char ( &_ArraySizeHelper( ... ))[N];
says “_ArraySizeHelper is afunction that returns a reference (note the &) to a char array of N elements”.
Next, the function parameter is
T (&array)[N]
which is a reference to a T arrayof N elements.
Finally, countof is defined as thesize of the result of the function _ArraySizeHelper. Note we don’t even need to define _ArraySizeHelper(), -- a declaration is enough.
With this new definition,
int x[10];
int y[ 2*countof(x) ]; // twice as big asx
becomes valid, just as we desire.
Am I happy now? Well, I think this definition is definitely better than the others wehave visited, but it is still not quite what I want. For one thing, it doesn’t work with types defined inside a function. That’s because the template function _ArraySizeHelper expects a type that is accessible in the global scope.
I don’t have a better solution. If you know one, please let me know.
BTW, how does one solve the same problem for C#? It’s trivial there. You just say “x.length()”(I forgot the actual syntax, but you should get the idea).
One thing to point out is that, in C# the count of anarray is not in its type. You decide how many elements are there whenyou create the array at run time. Therefore, don’t even try to derive this information at compile time.
- How Would You Get the Count of an Array in C++?
- How Would You Get the Count of an Array in C++?
- 在C++中怎样获得数组的大小?(原文标题:How Would You Get the Count of an Array in C++?)
- Given an array of characters. How would you reverse it.
- How can I get the IPv4 address of an interface in linux from C code ?
- How would you test an ATM Machine?
- How to define an array in c#.
- How to initialize an array in C
- How do I sort an array of hashes by a value in the hash?
- How do you get the length of a string in jQuery?
- uiview 某点返回 色值 How to get the color of a pixel in an UIView?
- 得到坐标的颜色值 How to get the color of a pixel in an UIView?
- How do I get the name of an object's type in JavaScript
- Get the rows count of all the table in Sybase
- Get nth Max number in an array of unsorted integers.
- Get nth element of an array in Ruby?
- Get indices for sorted permutation of an array in Ruby?
- how to get the value of an control
- 0/1背包问题 详解
- 自定义网络包-长度表示
- C#绘制矢量图(Metafile,WMF,EMF)
- 简单的计数器。。。。(scanf和getchar()的区别)。。。(一个错误很久没有找出来,最后是一个回车,中文下面的回车,编译不支持)
- 完全背包问题
- How Would You Get the Count of an Array in C++?
- ubuntu 安装SCIM(中文输入法)
- C# 内容分页
- div强制换行和强制不换行
- 比较有用的宗旨
- android telephony 模块makefile, .config , Rules.make
- android telephony 模块makefile, .config , Rules.make
- android telephony 模块.config
- 移动互联网发展趋势-移动互联网规模超40亿