歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> 關於Linux >> uclinux-2008R1-RC8(bf561)到VDSP5的移植(35):ARRAY_SIZE

uclinux-2008R1-RC8(bf561)到VDSP5的移植(35):ARRAY_SIZE

日期:2017/3/3 16:43:31   编辑:關於Linux

在include/linux/kernel.h中有一個定義:

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

這個宏定義用於取得一個數組中元素的個數,與一般定義不同的是,這個定義加上了+ __must_be_array(arr)這個尾巴,看下它的定義:

/* Force a compilation error if condition is true, but also produce a
result (of value 0 and type size_t), so the expression can be used
e.g. in a structure initializer (or where-ever else comma expressions
aren't permitted). */
#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
/* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a) /
BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))

在這裡__builtin_types_compatible_p是gcc內置的一個定義,對它的作用有這樣一個說明:

— Built-in Function: int __builtin_types_compatible_p (type1, type2)

You can use the built-in function __builtin_types_compatible_p to determine whether two types are the same.

This built-in function returns 1 if the unqualified versions of the types type1 and type2 (which are types, not expressions) are compatible, 0 otherwise. The result of this built-in function can be used in integer constant expressions.

This built-in function ignores top level qualifiers (e.g., const, volatile). For example, int is equivalent to const int.

The type int[] and int[5] are compatible. On the other hand, int and char * are not compatible, even if the size of their types, on the particular architecture are the same. Also, the amount of pointer indirection is taken into account when determining similarity. Consequently, short * is not similar to short **. Furthermore, two types that are typedefed are considered compatible if their underlying types are compatible.

An enum type is considered to be compatible with another enum type. For example, enum {foo, bar} is similar to enum {hot, dog}.

You would typically use this function in code whose execution varies depending on the arguments' types. For example:

            #define foo(x)                                                  /
({ /
typeof (x) tmp; /
if (__builtin_types_compatible_p (typeof (x), long double)) /
tmp = foo_long_double (tmp); /
else if (__builtin_types_compatible_p (typeof (x), double)) /
tmp = foo_double (tmp); /
else if (__builtin_types_compatible_p (typeof (x), float)) /
tmp = foo_float (tmp); /
else /
abort (); /
tmp; /
})

Note: This construct is only available for C.

它返回0或者1的結果,把它代入到BUILD_BUG_ON_ZERO定義中就可以發現,當返回值為0時,BUILD_BUG_ON_ZERO就變成了

#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1]) - 1)

顯然,此時BUILD_BUG_ON_ZERO這個宏將返回0。而當__builtin_types_compatible_p為1時,BUILD_BUG_ON_ZERO就變成了

#define BUILD_BUG_ON_ZERO(e) (sizeof(char[-1]) - 1)

顯然會造成語法錯誤,這也是注釋中說明Force a compilation error的原因。

ARRAY_SIZE這樣的定義在VDSP中是無法通過的,但是由於__must_be_array(arr)的作用僅僅在於添加一個編譯時的檢查,我們直接改為:

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

Copyright © Linux教程網 All Rights Reserved