glib常⽤库函数和⼀些定义
glib库是Linux平台下最常⽤的C语⾔函数库,它具有很好的可移植性和实⽤性。
glib是Gtk +库和Gnome的基础。glib可以在多个平台下使⽤,⽐如Linux、Unix、Windows等。glib为许多标准的、常⽤的C语⾔结构提供了相应的替代物。
使⽤glib库的程序都应该包含glib的头⽂件glib.h。
>>>>>## glib基本类型定义: >>>>>>
整数类型:
gint8、guint8、gint16、guint16、gint32、guint32、gint64、guint64。
不是所有的平台都提供64位整型,如果⼀个平台有这些, glib会定义G_HAVE_GINT64。
类型gshort、glong、gint和short、long、int完全等价。
布尔类型:
gboolean:它可使代码更易读,因为普通C没有布尔类型。
Gboolean可以取两个值:TRUE和FALSE。实际上FALSE定义为0,⽽TRUE定义为⾮零值。
字符型:
gchar和char完全⼀样,只是为了保持⼀致的命名。
浮点类型:
gfloat、gdouble和float、double完全等价。
指针类型:
gpointer对应于标准C的void *,但是⽐void *更⽅便。
指针gconstpointer对应于标准C的const void *(注意,将const void *定义为const gpointer是⾏不通的
>>>>>## glib的宏 >>>>>>
⼀些常⽤的宏列表
#include <glib.h>
TRUE
FALSE
NULL
MAX(a, b)
MIN(a, b)
ABS ( x )
CLAMP(x, low, high)
TRUE / FALSE / NULL就是1 / 0 / ( ( v o i d * ) 0 )。
MIN ( ) / MAX ( )返回更⼩或更⼤的参数。
ABS ( )返回绝对值。
CLAMP(x,low,high )若X在[low,high]范围内,则等于X;如果X⼩于low,则返回low;如果X⼤于high,则返
回high。
有些宏只有g l i b拥有,例如在后⾯要介绍的gpointer-to-gint和gpointer-to-guint。
⼤多数glib的数据结构都设计成存储⼀个gpointer。如果想存储指针来动态分配对象,可以这样做。
在某些情况下,需要使⽤中间类型转换。
//
gint my_int;
gpointer my_pointer;
my_int = 5;
my_pointer = GINT_TO_POINTER(my_int);
printf("We are storing %d/n", GPOINTER_TO_INT(my_pointer));
//
这些宏允许在⼀个指针中存储⼀个整数,但在⼀个整数中存储⼀个指针是不⾏的。
如果要实现的话,必须在⼀个长整型中存储指针。
宏列表:
在指针中存储整数的宏
#include <glib.h>
GINT_TO_POINTER ( p )
GPOINTER_TO_INT ( p )
GUINT_TO_POINTER ( p )
GPOINTER_TO_UINT ( p )
调试宏:
定义了G_DISABLE_CHECKS或G_DISABLE_ASSERT之后,编译时它们就会消失.
宏列表:
前提条件检查
#include <glib.h>
g_return_if_fail ( condition )
g_return_val_if_fail(condition, retval)
///
使⽤这些函数很简单,下⾯的例⼦是g l i b中哈希表的实现:
void g_hash_table_foreach (GHashTable *hash_table,GHFunc func,gpointer user_data)
{
GHashNode *node;
gint i;
g_return_if_fail (hash_table != NULL);
g_return_if_fail (func != NULL);
for (i = 0; i < hash_table->size; i++)
for (node = hash_table->nodes[i]; node; node = node->next)
(* func) (node->key, node->value, user_data);
}
///
宏列表:
断⾔
#include <glib.h>
g_assert( condition )
g_assert_not_reached ( )
如果执⾏到这个语句,它会调⽤abort()退出程序并且(如果环境⽀持)转储⼀个可⽤于调试的core⽂件。
断⾔与前提条件检查的区别:
应该断⾔⽤来检查函数或库内部的⼀致性。
g_return_if_fail()确保传递到程序模块的公⽤接⼝的值是合法的。
如果断⾔失败,将返回⼀条信息,通常应该在包含断⾔的模块中查错误;
如果g_return_if_fail()检查失败,通常要在调⽤这个模块的代码中查错误。
//
下⾯glib⽇历计算模块的代码说明了这种差别:
GDate * g_date_new_dmy (GDateDay day, GDateMonth m, GDateYear y)
{
GDate *d;
g_return_val_if_fail (g_date_valid_dmy (day, m, y), NULL);
d = g_new (GDate, 1);
d->julian = FALSE;
d->dmy = TRUE;
d->month = m;
d->day = day;
d->year = y;
g_assert (g_date_valid (d));
return d;
}
/
/
开始的预条件检查确保⽤户传递合理的年⽉⽇值;
结尾的断⾔确保glib构造⼀个健全的对象,输出健全的值。
断⾔函数g_assert_not_reached() ⽤来标识“不可能”的情况,通常⽤来检测不能处理的
所有可能枚举值的switch语句:
switch (val)
{
case FOO_ONE:
break ;
case FOO_TWO:
break ;
default:
/* ⽆效枚举值* /
g_assert_not_reached ( ) ;
break ;
}
所有调试宏使⽤glib的g_log()输出警告信息,g_log()的警告信息包含发⽣错误的应⽤程序或库函数名字,并且还可以使⽤⼀个替代的警告打印例程.
>>>>>## 内存管理 >>>>>>
glib⽤⾃⼰的g_变体包装了标准的malloc()和free(),即g_malloc()和g_free()。
它们有以下⼏个⼩优点:
字符串比较函数实现* g_malloc()总是返回gpointer,⽽不是char *,所以不必转换返回值。
* 如果低层的malloc()失败,g_malloc()将退出程序,所以不必检查返回值是否是NULL。
* g_malloc() 对于分配0字节返回NULL。
* g_free()忽略任何传递给它的NULL指针。
函数列表: glib内存分配
#include <glib.h>
gpointer g_malloc(gulong size)
void g_free(gpointer mem)
gpointer g_realloc(gpointer mem,gulong size)
gpointer g_memdup(gconstpointer mem,guint bytesize)
g_realloc()和realloc()是等价的。
g_malloc0(),它将分配的内存每⼀位都设置为0;
g_memdup()返回⼀个从mem开始的字节数为bytesize的拷贝。
为了与g_malloc()⼀致,g_realloc()和g_malloc0()都可以分配0字节内存。
g_memdup()在分配的原始内存中填充未设置的位,⽽不是设置为数值0。
宏列表:内存分配宏
#include <glib.h>
g_new(type, count)
g_new0(type, count)
g_renew(type, mem, count)
>>>>>## 字符串处理 >>>>>>
如果需要⽐gchar *更好的字符串,glib提供了⼀个GString类型。
函数列表: 字符串操作
#include <glib.h>
gint g_snprintf(gchar* buf,gulong n,const gchar* format,. . . )
gint g_strcasecmp(const gchar* s1,const gchar* s2)
gint g_strncasecmp(const gchar* s1,const gchar* s2,guint n)
在含有snprintf()的平台上,g_snprintf()封装了⼀个本地的snprintf(),并且⽐原有实现更稳定、安全。
以往的snprintf()不保证它所填充的缓冲是以NULL结束的,但g_snprintf()保证了这⼀点。
g_snprintf函数在buf参数中⽣成⼀个最⼤长度为n的字符串。其中format是格式字符串,“...”是要插⼊的参数。
函数列表: 修改字符串
#include <glib.h>
void g_strdown(gchar* string)
void g_strup(gchar* string)
void g_strreverse(gchar* string)
gchar* g_strchug(gchar* string)
gchar* g_strchomp(gchar* string)
宏g_strstrip()结合以上两个函数,删除字符串前后的空格。
函数列表: 字符串转换
#include <glib.h>
gdouble g_strtod(const gchar* nptr,gchar** endptr)
gchar* g_strerror(gint errnum)
gchar* g_strsignal(gint signum)
函数列表: 分配字符串
#include <glib.h>
gchar * g_strdup(const gchar* str)
gchar* g_strndup(const gchar* format,guint n)
gchar* g_strdup_printf(const gchar* format,. . . )
gchar* g_strdup_vprintf(const gchar* format,va_list args)
gchar* g_strescape(gchar* string)
gchar* g_strnfill(guint length,gchar fill_char)
/
gchar* str = g_malloc(256);
g_snprintf(str, 256, "%d printf-style %s", 1, "format");
⽤下⾯的代码,不需计算缓冲区的⼤⼩:
gchar* str = g_strdup_printf("%d printf-style %", 1, "format") ;
/
函数列表:连接字符串的函数
#include <glib.h>
gchar* g_strconcat(const gchar* string1,. . . )
gchar* g_strjoin(const gchar* separator,. . . )
函数列表: 处理以NULL结尾的字符串向量
#include <glib.h>
gchar** g_strsplit(const gchar* string,const gchar* delimiter,gint max_tokens)
gchar* g_strjoinv(const gchar* separator,gchar** str_array)
void g_strfreev(gchar** str_array)
>>>>>## 数据结构 >>>>>>链表~~~~~~~~~~
glib提供了普通的单向链表和双向链表,分别是GSList 和GList。
创建链表、添加⼀个元素的代码:
GSList* list = NULL;
gchar* element = g_strdup("a string");
list = g_slist_append(list, element);
删除上⾯添加的元素并清空链表:
list = g_slist_remove(list, element);
为了清除整个链表,可使⽤g_slist_free(),它会快速删除所有的链接;
g_slist_free()只释放链表的单元,它并不知道怎样操作链表内容。
访问链表的元素,可以直接访问GSList结构:
gchar* my_data = list->data;
为了遍历整个链表,可以如下操作:
GSList* tmp = list;
while (tmp != NULL)
{
printf("List data: %p/n", tmp->data);
tmp = g_slist_next(tmp);
}
/
下⾯的代码可以⽤来有效地向链表中添加数据:
void efficient_append(GSList** list, GSList** list_end, gpointer data)
{
g_return_if_fail(list != NULL);
g_return_if_fail(list_end != NULL);
if (*list == NULL)
{
g_assert(*list_end == NULL);
*list = g_slist_append(*list, data);
*list_end = *list;
}
else
{
*list_end = g_slist_append(*list_end, data)->next;
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。

发表评论