LINUX_LIST操作笔记

本文详细介绍了C语言中使用宏定义进行链表操作的方法,包括单行宏定义的不同用法、0地址的理解及其应用,并通过具体示例展示了如何在实际项目中实现链表的增删查改。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在项目中发现有一个很经典的链表操作,实现了结构中的成员与链表记录指针分离(C实现面象对象),而且整个链表的相关操作都是采用宏定义。

读懂内部操作查询了以下知识:

 

1、 单行宏定义的用法:主要有以下三种用法.
   1) 前加##或后加##,将标记作为一个合法的标识符的一部分.注意,不是字符串.多用于多行的宏定义中.例如:
#define A(x)  T_##x
则 int A(1) = 10; //等效于int T_1 = 10;
#define A(x)  Tx##__
则 int A(1) = 10; //等效于int T1__ = 10;
   2) 前加#@,将标记转换为相应的字符,注意:仅对单一标记转换有效(理解有误?)
 #define B(x) #@x
 则B(a)即’a’,B(1)即’1’.但B(abc)却不甚有效.
   3) 前加#,将标记转换为字符串.
 #define C(x) #x
 则C(1+1) 即 ”1+1”.

 

在#define中,标准只定义了#和##两种操作。#用来把参数转换成字符串,##则用来连接前后两个参数,把它们变成一个字符串。  
#include <stdio.h>  
#define paster( n ) printf( "token " #n" = %d\n ", token##n )  
int main()  
{  
int token9=10;  
paster(9);  
return 0;  
}  
输出为[leshy@leshy src]$ ./a.out  token 9 = 10 

 

2、0地址(让我重新认识了0地址)

/* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.*/
#define list_entry(ptr, type, member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
 
 
.(unsigned long)(&((type *)0)->member)))
这个有个0地址,实际上也就是求结构中member在这个结构中的偏移位置。
 

把0作为结构的地址,(&((type *)0)->member)为以0为地址的结构,结构中元素member的地址。
换句话说,求出了结构type中元素member的偏移值。

&操作如果是对一个表达式,而不是一个标识符,会取消操作,而不是添加。
比如&*a,会直接把a的地址求出来,不会访问*a。
&a->member,会把访问a->member的操作取消,只会计算出a->member的地址。

 
3、相关用法(自已已验证)。
1)链表操作
 
ListNode gTestListHead;

typedef struct
{
 int index;
 ListNode node;

}TestStruct;


void test()
{
 int32_t i =0;
 ListNode *pListNode = NULL;   //链表结点
 TestStruct *pStructNode = NULL;  //结构结点

 ListNode *pListNodeTemp = NULL;  //销毁时保存被销毁的下一个结点,方便找到下一个结点

 INIT_LIST_HEAD(&gTestListHead);

 for (i=0; i< 10; i++)
 {
  pStructNode = (TestStruct*)malloc(sizeof(TestStruct));

  pStructNode->index = i * 10;

  //将结点加入到链表尾部
  list_add_tail(&(pStructNode->node), &gTestListHead);
 }

  //遍历链表
  list_for_each(pListNode, &gTestListHead)
  {
   list_get_object(TestStruct, node, pListNode, pStructNode);
   printf("结点 %d \r\n",pStructNode->index);
  }

 //销毁链表
 list_for_each_safe(pListNode, pListNodeTemp, &gTestListHead)
 {
  pStructNode = list_entry(pListNode, TestStruct, node);
  list_del(&(pStructNode->node));

  i --;
  free(pStructNode);
  pStructNode = NULL;
 }

 INIT_LIST_HEAD(&gTestListHead);
 printf("最后i的值 %d \r\n", i);
}


 2)stack操作
等待
3)FIFO操作 
等待
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值