数组大小的宏拒绝指针

编程入门 行业动态 更新时间:2024-10-24 12:33:22
本文介绍了数组大小的宏拒绝指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

这是经常教导标准数组大小宏

The standard array-size macro that is often taught is

#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))

或某些等价形式。然而,这种事情时,指针传递在默默的成功,并且给出的结果,可以在运行时似乎是可信直到事情神秘地土崩瓦解。

or some equivalent formation. However, this kind of thing silently succeeds when a pointer is passed in, and gives results that can seem plausible at runtime until things mysteriously fall apart.

这一切都太容易犯这个错误:具有本地数组变量重构功能,动了一下数组处理成调用数组作为参数新功能

It's all-too-easy to make this mistake: a function that has a local array variable is refactored, moving a bit of array manipulation into a new function called with the array as a parameter.

所以,问题是:是否有卫生宏在编译时pferably检测 ARRAYSIZE 宏滥用在C,$ P $?在C ++中,我们只希望使用专门用于仅数组参数的模板;在C,看来我们需要一些方法来区分数组和指针。 (如果我想拒绝的阵列,比如,我只是做例如(ARR =改编,...)因为数组赋值是非法的)。

So, the question is: is there a "sanitary" macro to detect misuse of the ARRAYSIZE macro in C, preferably at compile-time? In C++ we'd just use a template specialized for array arguments only; in C, it seems we'll need some way to distinguish arrays and pointers. (If I wanted to reject arrays, for instance, I'd just do e.g. (arr=arr, ...) because array assignment is illegal).

推荐答案

Linux内核使用一个很好的实施 ARRAY_SIZE 来解决这个问题:

Linux kernel uses a nice implementation of ARRAY_SIZE to deal with this issue:

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))

#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))

#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))

当然,这仅仅是在GNU C便携,因为它利用了两个instrinsics的:   的typeof 运营商和 __ builtin_types_compatible_p 功能。此外,它使用自己的名牌 BUILD_BUG_ON_ZERO 宏这是只有在GNU C。

Of course this is portable only in GNU C as it makes use of two instrinsics: typeof operator and __builtin_types_compatible_p function. Also it uses their "famous" BUILD_BUG_ON_ZERO macro which is only valid in GNU C.

假设一个编译时评估的要求(这是我们想要的),我不知道任何便携执行这个宏的。

Assuming a compile time evaluation requirement (which is what we want), I don't know any portable implementation of this macro.

一个半便携的实施(且不会涵盖所有情况下)是:

A "semi-portable" implementation (and which would not cover all cases) is:

#define ARRAY_SIZE(arr) \ (sizeof(arr) / sizeof((arr)[0]) + STATIC_EXP(IS_ARRAY(arr)))

#define IS_ARRAY(arr) ((void*)&(arr) == &(arr)[0]) #define STATIC_EXP(e) \ (0 * sizeof (struct { int ARRAY_SIZE_FAILED:(2 * (e) - 1);}))

使用 GCC 这一点,如果参数是 -std = C99 -Wall ,但 -pedantic 将发出警告。原因是 IS_ARRAY 前pression是不是一个整数常量前pression(转换为指针类型和下标操作者不得在整型常量前pressions)和 STATIC_EXP 位字段宽度需要整型常量前pression。

With gcc this gives no warning if argument is an array in -std=c99 -Wall but -pedantic would gives a warning. The reason is IS_ARRAY expression is not an integer constant expression (cast to pointer types and subscript operator are not allowed in integer constant expressions) and the bit-field width in STATIC_EXP requires an integer constant expression.

更多推荐

数组大小的宏拒绝指针

本文发布于:2023-07-29 00:49:09,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1235708.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:数组   指针   大小

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!