C语言结构体高级篇,linux内核链表

昨天初步学习了linux内核链表,记录一下

首先要先知道结构体的一个很隐秘的知识点,如下:

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

typedef struct Worker
{
	char name[30];
	int nNumber;
};

int main()
{
	struct Worker* pworker = NULL;
	char* name;
	char s;
	int nNumber;
	int pNum;

	// 下面两行不会崩溃,因为->是取地址符,只是获取相对于结构体其实地点的偏移量,且pNum = 32;
	// 多扯一点,为什么会是32二不是三十呢,因为c++编译器是四字节整体分配内存的,不满四字节按四字节分配,不信的可以自己试一下
	
	name = pworker->name;
	pNum = &(pworker->nNumber);
	

	// 对于上面两行即使这样写也是可以的,根上面的效果一样的,
	// Linux内核有个宏就是这样写的 #define offsetof(s,m) (size_t)&(((s *)0)->m),求取偏移地址
	name = ((struct Worker*)0)->name;
	pNum = &(((struct Worker*)0)->nNumber);

	// 下面两行会崩溃,因为直接去读取非法内存值
	s = name[0];
	nNumber = pworker->nNumber;

	return 0;
}
有了这个基础就可以理解Linux内核链表了

typedef struct _tag_LinkListNode
{
	struct _tag_LinkListNode* next;
}LinkListNode;

typedef struct _Teacher
{
	char name[32];
	int age ;
	// 可以通过上面介绍的方法求出node相对于结构体其实位置的偏移地址
	// 相反的,是不是如果我知道node的地址后就可以根据偏移地址来求结构体的起始地址了
	LinkListNode node;  
}Teacher;
那么下面我们就可以创建一个node的链表,然后将  Teacher插入到链表内。

传统链表是将链表操作和业务混合到一块了,如下图

C语言结构体高级篇,linux内核链表_第1张图片

Linux链表则实现了分离,如下图

C语言结构体高级篇,linux内核链表_第2张图片

我们可以向pHead中添加Teacher节点

我们可以将创建的Teacher中的LinkListNode的首地址添加打pHead,然后在对链表操作的时候看一通过偏移地址来找到具体的结构体,当然有个比较方便的方法,那就是将LinkListNode node放在结构体的第一位,这样偏移量是0,他们的地址就重合和,会省去很多麻烦的操作。


感觉这种链表就好比给针穿线,链表相当于线,结构体相当于针,每个结构体都有一个针孔,用线把他们传串到一起

你可能感兴趣的:(C/C++基础的系统学习)