C语言宏定义-再看ARRAY_SIZE
1. 简介
做过linux驱动开发的人员,应该都用过ARRAY_SIZE(x)
宏,目的求出数组包含的最大个数,在2007内核提交了一个patch,更新了这个宏加入__must_be_array(arr)是防止被误用,比如传入的是指针而不是数组。
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]) + __must_be_array(arr))
2. __BUILTIN_TYPES_COMPATIBLE_P
名字:
__builtin_types_compatible_p
GNU扩展,用来判断两个类型是否相同。(PS: GCC提供了一系列的builtin函数,可以实现一些简单快捷的功能来方便程序编写,另外,很多builtin函数可用来优化编译结果。这些函数以“_builtin”作为函数名前缀。)
原型:
int __builtin_types_compatible_p(type_a, type_b);
描述:
此函数为GNU扩展,判断type_a
和type_b
是否是相同的数据类型,相同返回1,否则返回0。该函数不区分const/volatile这样的修饰符,即int和const int被认为是相同的类型。
请注意一下情景:
-
两个类型的sizeof值跟它的类型判断是相互不影响的,例如:在i386架构下,
sizeof(char *)
和sizeof(int)
的值是相同的,但是他们的类型却是不相同的。 -
限定符会被忽略,例如
const int
和int
他们的类型是相同的。 -
相同的类型不同的指针级数是不相同的例如:
double*
和double**
是不相同的。 -
连个用
typedef
定义的类型,当且进档他们定义的类型是相同的时候,=它们是相同的。 -
enum
类型是一种特殊的情况,两个enum
类型是不相同的。
3. typeof()关键字
typeof() 是GUN C提供的一种特性,可参考C-Extensions,它可以取得变量或者表达式的类型,这个特性在linux内核中应用非常广泛。
具体使用方法参考:C语言中typeof()函数的用法
4. 相关宏
CMO_ARRAY_SIZE(array) | 计算一个数组的最大个数 |
---|---|
CMO_PART_OF_ARRAY(array, ptr) | 判断是否指针是否在array内存范围内 |
CMO_MEMBER_SIZE(structure, member) | 计算结构体成员大小 |
CMO_MEMBER_ARRAYSIZE(structure, member) | 计算结构体数组类成员的最大个数 |
CMO_MEMBER_DELTA(structure, member1, member2) | 计算结构体中两个成员的偏移差值 |
/* Auxiliary Marco, evaluates to 0 if array is an array; compile error if not
* array (e.g. pointer).
*/
#if (CMO__HAVE_TYPEOF && CMO__HAVE_BUILTIN_TYPES_COMPATIBLE_P)
#define __cmo_must_be_array(array) \
CMO_STATIC_ASSERT_OR_ZERO(!__builtin_types_compatible_p( \
__typeof__(array), __typeof__(&(array)[0])))
#else
#define __cmo_must_be_array(array) (0)
#endif /* (CMO__HAVE_TYPEOF && CMO__HAVE_BUILTIN_TYPES_COMPATIBLE_P) */
/**
* @def CMO_PART_OF_ARRAY
* @brief Evaluates to 1 if ptr is part of array, 0 otherwise; compile error if
* "array" argument is not an array (e.g. "ptr" and "array" mixed up)
*/
#define CMO_PART_OF_ARRAY(array, ptr) \
((ptr) && ((void *)(ptr) >= (void *)&((array)[0]) && \
(void *)(ptr) < (void *)&((array)[CMO_ARRAY_SIZE(array)])))
/**
* @def CMO_MEMBER_SIZE
* @brief Calc structure of member size.
*
* Example:
* @code
* struct a = {
* uint32_t m1;
* uint32_t m2;
* };
* size_t size_m2;
*
* size_m2 = CMO_MEMBER_SIZE(a, m2); //size_m2 = 4
* @endcode
*/
#define CMO_MEMBER_SIZE(structure, member) (sizeof(((structure *)0)->member))
/**
* @def CMO_MEMBER_ARRAYSIZE
* @brief Calc structure of member array size(Number of entries in an array).
*
* Example:
* @code
* struct a = {
* uint32_t m1;
* uint32_t m2[6];
* };
* size_t arraysize_m2;
*
* arraysize_m2 = CMO_MEMBER_ARRAYSIZE(a, m2); //arraysize_m2 = 6
* @endcode
*/
#define CMO_MEMBER_ARRAYSIZE(structure, member) \
(CMO_MEMBER_SIZE(structure, member) / \
CMO_MEMBER_SIZE(structure, member[0]))
/**
* @def CMO_MEMBER_DELTA
* @brief Delta from start of one member to the start of another member.
*
* Example:
* @code
* struct a = {
* uint32_t m1;
* uint32_t m2;
* };
* int delta_m1_m2;
*
* delta_m1_m2 = CMO_MEMBER_DELTA(a, m1, m2); //delta_m1_m2 = -4
* @endcode
*/
#define CMO_MEMBER_DELTA(structure, member1, member2) \
((int)offsetof(structure, member1) - (int)offsetof(structure, member2))