概览
为了使用的方便,GLib定了常用的一些宏,比如MIN、MAX等。
涉及内容
布尔类型
TRUE、FALSE、NULL的含义不说自明。
#define FALSE (0)
#define TRUE (!FALSE)
#define NULL ((void *)0)
整数相关
整数与指针相互转换
为了提高程序效率,在Glib、GTK等一些库中,为了函数中参数传递的数据常常为指针。特别地,对于32位整数类型,GLib提供4个宏,方便整数与指针的相互转换:
- 有符号整数:GINT_TO_POINTER(i)、GPOINTER_TO_INT( p )
- 无符号整数:GUINT_TO_POINTER(u)、GPOINTER_TO_UINT( p )
举个简单的例子如下:
#include <glib.h>
int main(int argc, char const *argv[]) {
gpointer p;
gint i = 10;
p = GINT_TO_POINTER(i);
gint j = GPOINTER_TO_INT(p);
g_print("%d\n", j);
guint m = -10;
p = GUINT_TO_POINTER(m);
guint n = GPOINTER_TO_UINT(p);
g_print("%d\n", n);
}
// 输出
10
-10
至于为什么这样设计,读者可以自行查阅官方的文档,这里仅抛出如下几个问题:
- 为什么不使用 int *ip?
- 为什么仅仅支持32位整数?
数字大小及截断
- MAX、MIN、ABS分别表示取最大、最小与绝对值。
- CLAMP(x, low, high)是截断函数,用于限制x的值位于low与high之间。
- G_APPROX_VALUE(a, b, epsilon)用于判断a与b差的绝对值是否小于epsilon,即在误差epsilon下,a与b是否足够接近。
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define ABS(a) (((a) < 0) ? -(a) : (a))
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#define G_APPROX_VALUE(a, b, epsilon) \
(((a) > (b) ? (a) - (b) : (b) - (a)) < (epsilon))
结构体相关
- G_SIZEOF_MEMBER(struct_type, member) 用于获取结构体struct_type中member的字节大小;
- G_STRUCT_OFFSET(struct_type, member) 用于获取结构体struct_type中member的偏移量大小;
- G_STRUCT_MEMBER(member_type, struct_p, struct_offset) 用于返回指向member_type类型的struct_p指针的偏移struct_offset字节的成员member;
- G_STRUCT_MEMBER_P(struct_p, struct_offset) 用于返回不确定类型的结构体struct_p指针的偏移struct_offset字节后的指针;
数组相关
define G_N_ELEMENTS(arr) 用于返回数组中元素的个数,数组的大小必须要在编译时是确定的。
#define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
系统相关
G_OS_WIN32、G_OS_UNIX只会在WINDOW或LINUX有定义,可以用来区分当前操作系统。
与之相关的还有目录分隔符G_DIR_SEPARATOR、搜索路径分隔符G_SEARCHPATH_SEPARATOR,分别都是字符。此外,还有相应返回字符串的版本G_**_SEPARATOR_S。比如,在LINUX下,G_DIR_SEPARATOR是’/‘,G_SEARCHPATH_SEPARATOR是’:'。
补充说明:上述中的目录分割符,也就是一般意义上的路径的分隔符。而搜索路径分隔符指定的是多个路径之间的分隔符,这个在环境变量中十分常见,linux下为 :,Windows下为**;**。
无返回函数的优化
针对与无返回函数,GNU C或MSVC在编译器中可能会有优化。G_NORETURN用来指明函数为无返回值,G_NORETURN_FUNCPTR用于指向无返回值的函数的指针。
# define G_NORETURN __attribute__ ((__noreturn__))
#define G_NORETURN_FUNCPTR
// 示例
G_NORETURN void g_abort (void);
G_NORETURN_FUNCPTR void (*funcptr) (void);
数值计算相关
几个常数
GLib定义了若干个常用的数值,比如
- G_E,自然常数e;
- G_LN2,以自然常数e为底2的对数,即 log e 2 = ln 2 \log_e2=\ln2 loge2=ln2;
- G_LN10,以自然常数e为底2的对数,即 log e 10 = ln 10 \log_e10=\ln10 loge10=ln10;
- G_PI,圆周率 π \pi π;
- G_PI_2,圆周率的一半 π / 2 \pi/2 π/2;
- G_PI_4,圆周率的四分之一 π / 4 \pi/4 π/4;
- G_SQRT2,根号2, 2 \sqrt{2} 2
- G_LOG_2_BASE_10,以10为底2的对数 log 10 2 \log_{10}2 log102.
IEEE754浮点数定义
IEEE754单精度 float、双精度double的结构定义
/* 单精度
* 31 30 23 22 0
* +--------+---------------+---------------+
* | s 1bit | e[30:23] 8bit | f[22:0] 23bit |
* +--------+---------------+---------------+
* B0------------------->B1------->B2-->B3-->
*
* 双精度
* 63 62 52 51 32 31 0
* +--------+----------------+----------------+ +---------------+
* | s 1bit | e[62:52] 11bit | f[51:32] 20bit | | f[31:0] 32bit |
* +--------+----------------+----------------+ +---------------+
* B0--------------->B1---------->B2--->B3----> B4->B5->B6->B7->
*/
此外,在联合体中分别对上述结构按段起了名字,同时指明了段是多少位。需要注意的是下面结构体mpn中的定义的顺序与前面所描述的是反过来的 (此处是小端模式,大端模式是一致的),读者可以自行对照。
union GFloatIEEE754 {
gfloat v_float;
struct {
guint mantissa : 23;
guint biased_exponent : 8;
guint sign : 1;
} mpn;
};
union GDoubleIEEE754 {
gdouble v_double;
struct {
guint mantissa_low : 32;
guint mantissa_high : 20;
guint biased_exponent : 11;
guint sign : 1;
} mpn;