更安全的阵列长度 [英] Safer Array Length

查看:66
本文介绍了更安全的阵列长度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



很多人使用类似于以下方法来确定

数组的长度:


#define NUMELEM(arr)(sizeof(arr)/ sizeof *(arr))


我记得读过Alf P. Steinbach写的一篇文章,其中列出了

几种确定数组长度的方法。他列出了每个人的专业和

骗局。


上述方法的一个原因是宏无法检测

是否错误地提供了指针而不是数组。 (它还是

评估arr两次,如果我们调用一个通过引用返回

数组的函数,那就不好了。)

为了克服前一个缺点,我已经制作了

。它不是成品,但你明白了:


#define NUMELEM(arr)(sizeof(arr)/ sizeof *(arr))


模板< int positive_or_negative>

struct VerifyType {

unsigned must_not_be_negative:positive_or_negative;

/ * Can'' t有负位字段* /

};


#define VERIFY(compile_time_constant)\

(sizeof(VerifyType< \

(compile_time_constant)?1:-1


>))



#define ARRLEN(arr)((void)VERIFY(NUMELEM(arr)1),NUMELEM(arr))


#include< iostream>

使用std :: cout;


int main()

{

int array [5];


int * p =数组;


cout<< ARRLEN(阵列)<< ''\ n'';


cout<< ARRLEN(p)<< \\\
; / *编译器错误* /

}


本质上,它只执行编译时断言以确保NUMELEM

(arr)大于一。当然,我们将有一些技术细节,例如长度为1的
阵列。


-


Frederick Gotham

解决方案



" Frederick Gotham" < fg ******* @ SPAM.com在留言中写道

news:zb ******************* @ news.indigo .ie ...


>

许多人使用类似于以下方法确定

数组的长度:


#define NUMELEM(arr)(sizeof(arr)/ sizeof *(arr))


我记得读过Alf P. Steinbach写的一篇文章,其中列出了几种确定数组长度的方法。他列出了每个人的专业和

骗局。


上述方法的一个原因是宏无法检测

是否

它是错误地提供指针而不是数组。 (它还是

评估arr两次,如果我们调用一个通过引用返回

数组的函数,那就不好了。)

为了克服前一个缺点,我已经制作了

。它不是成品,但你明白了:


#define NUMELEM(arr)(sizeof(arr)/ sizeof *(arr))


模板< int positive_or_negative>

struct VerifyType {

unsigned must_not_be_negative:positive_or_negative;

/ * Can'' t有负位字段* /

};


#define VERIFY(compile_time_constant)\

(sizeof(VerifyType< \

(compile_time_constant)?1:-1


>))



#define ARRLEN(arr)((void)VERIFY(NUMELEM(arr)1),NUMELEM(arr))


#include< iostream>

使用std :: cout;


int main()

{

int array [5];


int * p =数组;


cout<< ARRLEN(阵列)<< ''\ n'';


cout<< ARRLEN(p)<< \\\
; / *编译器错误* /

}


本质上,它只执行编译时断言以确保

NUMELEM

(arr)大于1。当然,我们将有一些技术细节,例如

数组,其长度为1.



为什么不消除上述问题呢?那些

一般会是宏吗?使用矢量代替,它''知道'它的大小。


std :: vector< intv(10);

v.push_back(0) ;

std :: cout<< v.size()<< \\\
; //打印11

-Mike


>

-


Frederick Gotham



Frederick Gotham发布:


#define VERIFY(compile_time_constant)\

(sizeof(VerifyType< \

(compile_time_constant)?1:-1


>))



#define ARRLEN(arr)((void)VERIFY(NUMELEM(arr)1),NUMELEM(arr))



我会重新定位void演员:


#define VERIFY(compile_time_constant)\

((void)sizeof(VerifyType< \

(compile_time_constant) )?1:-1


>))



#define ARRLEN(arr)(VERIFY(NUMELEM(arr) )1),NUMELEM(arr))


-


Frederick Gotham


< blockquote> Frederick Gotham发布:


我将重新定位void演员:



我在路上留下了一些必要的括号。我会重写

整件事:


#define NUMELEM(arr)(sizeof(arr)/ sizeof *(arr))


模板< int positive_or_negative>

struct VerifyType {

unsigned must_not_be_negative:positive_or_negative;

/ *不能有负位字段* /

};


#define VERIFY(compile_time_constant)\

( (void)sizeof(VerifyType< \

(compile_time_constant)?1:-1


>))



#define ARRLEN(arr)(VERIFY(NUMELEM((arr))1),NUMELEM((arr)))


#include< iostream>

使用std :: cout;


int main()

{

int array [ 5];


int * p =数组;


cout<< ARRLEN(阵列)<< ''\ n'';


cout<< ARRLEN(p)<< \\\
; / *编译器错误* /

}


-


Frederick Gotham


Many people use a method quite akin to the following to determine an
array''s length:

#define NUMELEM(arr) (sizeof (arr) / sizeof *(arr))

I recall reading an article written by Alf P. Steinbach which listed
several methods of determining an array''s length. He listed the pro''s and
con''s of each.

One of the con''s of the above method is that the macro can''t detect whether
it is erronously supplied with a pointer instead of an array. (It also
evaluates "arr" twice, which is bad if we call a function which returns an
array by reference!).

In an attempt to overcome the former shortcoming, I''ve cooked up the
following. It''s not a finished product, but you get the idea:

#define NUMELEM(arr) (sizeof (arr) / sizeof *(arr))

template <int positive_or_negative>
struct VerifyType {
unsigned must_not_be_negative : positive_or_negative;
/* Can''t have negative bit field */
};

#define VERIFY(compile_time_constant) \
( sizeof(VerifyType< \
(compile_time_constant) ? 1 : -1

>) )

#define ARRLEN(arr) ((void)VERIFY(NUMELEM(arr) 1), NUMELEM(arr))

#include <iostream>
using std::cout;

int main()
{
int array[5];

int *p = array;

cout << ARRLEN(array) << ''\n'';

cout << ARRLEN(p) << ''\n''; /* Compiler ERROR */
}

In essence, it simply performs a compile-time assert to ensure that NUMELEM
(arr) is greater than one. Of course, we''ll have technicalities such as
arrays whose length is 1.

--

Frederick Gotham

解决方案


"Frederick Gotham" <fg*******@SPAM.comwrote in message
news:zb*******************@news.indigo.ie...

>
Many people use a method quite akin to the following to determine an
array''s length:

#define NUMELEM(arr) (sizeof (arr) / sizeof *(arr))

I recall reading an article written by Alf P. Steinbach which listed
several methods of determining an array''s length. He listed the pro''s and
con''s of each.

One of the con''s of the above method is that the macro can''t detect
whether
it is erronously supplied with a pointer instead of an array. (It also
evaluates "arr" twice, which is bad if we call a function which returns an
array by reference!).

In an attempt to overcome the former shortcoming, I''ve cooked up the
following. It''s not a finished product, but you get the idea:

#define NUMELEM(arr) (sizeof (arr) / sizeof *(arr))

template <int positive_or_negative>
struct VerifyType {
unsigned must_not_be_negative : positive_or_negative;
/* Can''t have negative bit field */
};

#define VERIFY(compile_time_constant) \
( sizeof(VerifyType< \
(compile_time_constant) ? 1 : -1

>) )


#define ARRLEN(arr) ((void)VERIFY(NUMELEM(arr) 1), NUMELEM(arr))

#include <iostream>
using std::cout;

int main()
{
int array[5];

int *p = array;

cout << ARRLEN(array) << ''\n'';

cout << ARRLEN(p) << ''\n''; /* Compiler ERROR */
}

In essence, it simply performs a compile-time assert to ensure that
NUMELEM
(arr) is greater than one. Of course, we''ll have technicalities such as
arrays whose length is 1.

Why not eliminate the above described problems as well as those
will macros in general? Use a vector instead, it ''knows'' its size.

std::vector<intv(10);
v.push_back(0);
std::cout << v.size() << ''\n''; // prints 11

-Mike

>
--

Frederick Gotham



Frederick Gotham posted:

#define VERIFY(compile_time_constant) \
( sizeof(VerifyType< \
(compile_time_constant) ? 1 : -1

>) )


#define ARRLEN(arr) ((void)VERIFY(NUMELEM(arr) 1), NUMELEM(arr))


I''ll relocate that "void" cast:

#define VERIFY(compile_time_constant) \
( (void)sizeof(VerifyType< \
(compile_time_constant) ? 1 : -1

>) )

#define ARRLEN(arr) (VERIFY(NUMELEM(arr) 1), NUMELEM(arr))

--

Frederick Gotham


Frederick Gotham posted:

I''ll relocate that "void" cast:


I''ve left a few necessary parentheses out along the way. I''ll re-write the
whole thing:

#define NUMELEM(arr) (sizeof (arr) / sizeof *(arr))

template <int positive_or_negative>
struct VerifyType {
unsigned must_not_be_negative : positive_or_negative;
/* Can''t have negative bit field */
};

#define VERIFY(compile_time_constant) \
( (void)sizeof(VerifyType< \
(compile_time_constant) ? 1 : -1

>) )

#define ARRLEN(arr) (VERIFY(NUMELEM((arr)) 1), NUMELEM((arr)))

#include <iostream>
using std::cout;

int main()
{
int array[5];

int *p = array;

cout << ARRLEN(array) << ''\n'';

cout << ARRLEN(p) << ''\n''; /* Compiler ERROR */
}

--

Frederick Gotham


这篇关于更安全的阵列长度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆