模块契约侵入式链表 API

错误

错误域为 xrt.list:

代码常量含义
1XLIST_ERROR_ARGUMENT空链表、节点或迭代器参数。
2XLIST_ERROR_STATE未初始化、节点归属错误或链接不一致。
3XLIST_ERROR_RANGE节点计数将溢出。
4XLIST_ERROR_MODIFIED迭代期间发生外部结构修改。

查询未命中、空链表弹出和迭代自然结束是正常结果,不制造错误。成功操作不会隐式清除 调用方先前保存的错误。

定位

链表不拥有节点,也不决定对象类型和分配方式。用户把 xlistnode 嵌入自己的对象, 对象可以来自栈、全局存储、XRT 堆或任意内存池。一个对象需要同时进入多个链表时, 嵌入多个独立节点即可。

每个节点保存 Prev、Next 和只读的 Owner。额外的所属链表指针让插入、删除、 移动和归属检查保持 O(1),同时能够确定性拒绝重复插入和跨链表删除。链表不内建 同步;多个线程读写同一链表时由调用方加锁。

连续数据使用 array,FIFO/LIFO 工作负载使用 queue / stack,拥有运行时类型值的 稀疏有序容器使用 typed_list。本模块不重复这些高层容器的分配和类型生命周期逻辑。

类型与初始化

XRT_LIST_INIT 和 XRT_LIST_NODE_INIT 用于静态或聚合初始化;动态对象使用 xrtListInit 和 xrtListNodeInit。初始化函数只用于新的存储,不能覆盖仍然持有节点 的链表或仍然已连接的节点。xrtListReady 判断链表是否初始化,xrtListValidate 以 O(n) 完整检查端点、所有权、双向链接和计数。

链表字段公开是为了零成本检查和调试,但调用方只能读取。直接改写 First、Last、 Count、Version、State 或活动节点的链接字段会破坏契约。

XRT_CONTAINER_OF(node, type, member) 从任意位置嵌入的节点恢复对象,不要求节点是 结构的第一个成员:

查询

  • xrtListEmpty / xrtListCount 返回空状态和节点数。
  • xrtListFirst / xrtListLast 返回借用端点,空链表返回 NULL。
  • xrtListPrev / xrtListNext 返回借用相邻节点。
  • xrtListOwner 返回节点所属链表,未连接节点返回 NULL。
  • xrtListContains 判断节点是否属于指定链表。
  • xrtListLinked 判断节点是否属于任意链表。

借用节点在被移除、弹出或清空后仍由用户拥有,但其 Prev、Next 和 Owner 会全部 恢复为 NULL,可以安全插入其他链表。

结构操作

xrtListPushFront / xrtListPushBack 在首尾插入未连接节点。 xrtListInsertBefore / xrtListInsertAfter 要求参考节点属于目标链表;参考位置不能用 NULL 表示,首尾便利路径由 Push 函数明确表达。

xrtListRemove 只分离节点,不释放对象。xrtListPopFront / xrtListPopBack 分离并 返回端点,空链表返回 NULL 且不设置错误。xrtListMoveFront / xrtListMoveBack 把已有节点移动到首尾,不改变计数。xrtListClear 先完整验证链表,再分离所有节点; 验证失败时不会部分清空。

所有成功的结构变化都会更新 Version。节点数使用 size_t,达到 SIZE_MAX 后新增 节点以 XERR_RANGE 拒绝,不发生回绕。

安全迭代

xlistiter 是调用方持有的外置状态,不分配内存:

xrtListIterBegin 正向迭代,xrtListIterRBegin 反向迭代。自然结束不设置错误。 xrtListIterRemove 只能删除最近一次 Next 返回的当前节点,并同步迭代版本;连续删除 两次会失败。通过其他 API 修改链表会使现有迭代器失效,下一次 Next/Remove 以 XLIST_ERROR_MODIFIED 拒绝。xrtListIterEnd 用于提前结束,允许传入 NULL。

API 索引

完整示例位于 examples/containers/list/main.c。

旧版资产决策

新版保留旧 LList Base 的侵入节点、双向遍历、首尾操作、任意内存来源和多链接对象 能力,并补齐节点所有权、size_t 计数、结构验证、安全迭代和结构化错误。旧宏缺少 do/while 边界,重复插入、外来参考和跨链表删除会静默损坏结构,因此不保留原名称和 布局。

旧自动分配 LList 把节点头与未对齐的匿名字节负载拼接,并重复承担固定池、队列、栈和 类型容器职责。该层不再恢复:低层链接使用本模块,分配复用使用 Pool,高层数据结构使用 Array/Queue/Stack/Typed List,避免第二套节点分配与类型生命周期实现。

类型与初始化

xlistnode类型

侵入式链表节点(不透明):由宿主对象嵌入,一个对象可嵌入多个独立节点分别挂入不同链表。

字段类型语义
Prevstruct xlistnode*前驱
Nextstruct xlistnode*后继
Ownerxlist*Owner
typedef struct xlistnode { struct xlistnode* Prev; struct xlistnode* Next; xlist* Owner; } xlistnode;

xlistiter类型

外置迭代器不分配内存,并允许通过专用操作删除当前节点。

字段类型语义
Listxlist*List
Nextxlistnode*后继
Currentxlistnode*Current
Versionuint64结构版本
ReverseboolReverse
typedef struct xlistiter { xlist* List; xlistnode* Next; xlistnode* Current; uint64 Version; bool Reverse; } xlistiter;

xlisterror类型

链表模块稳定错误代码。

值语义
XLIST_ERROR_ARGUMENT参数非法
XLIST_ERROR_STATE状态非法
XLIST_ERROR_RANGE范围越界
XLIST_ERROR_MODIFIED迭代期间被修改
typedef enum xlisterror { XLIST_ERROR_ARGUMENT = 1, XLIST_ERROR_STATE, XLIST_ERROR_RANGE, XLIST_ERROR_MODIFIED } xlisterror;

xlist类型

侵入式链表不拥有节点内存;一个对象可嵌入多个独立节点。 不透明句柄或别名;生命周期与所有权见各使用方 API 节。

typedef struct xlist xlist;

xrtListInit函数

初始化新的链表存储;不能用于仍然持有节点的活动链表。

void xrtListInit(xlist* pList)

参数

参数方向约束说明
pList输出非空接收空链表
返回值
返回含义失败时状态
无纯初始化—
错误
  • 无 — 初始化不失败

范例已编译验证

containers/list_tour · 生命周期 · 观察

	xrtListInit(&List);

xrtListNodeInit函数

初始化新的节点存储;不能用于仍然属于链表的节点。

void xrtListNodeInit(xlistnode* pNode)

参数

参数方向约束说明
pNode输出非空接收独立状态节点
返回值
返回含义失败时状态
无纯初始化(恢复未连接状态)—
错误
  • 无 — 初始化不失败

范例已编译验证

containers/list_tour · 生命周期 · 观察

		xrtListNodeInit(&Entries[i].Node);

xrtListReady函数

判断链表是否已经初始化。

bool xrtListReady(const xlist* pList)

参数

参数方向约束说明
pList输入非空链表
返回值
返回含义失败时状态
true已初始化—
false未初始化纯查询
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 查询 · 观察

	if ( !xrtListReady(&List) ||
		!xrtListEmpty(&List) ||
		(xrtListCount(&List) != 0u) ||
		!xrtListValidate(&List) ||
		(xrtListFirst(&List) != NULL) ||
		(xrtListLast(&List) != NULL) ||
		(xrtListPopFront(&List) != NULL) ||
		(xrtListPopBack(&List) != NULL) ) {

xrtListValidate函数

完整验证节点所有权、双向链接、端点和计数(调试/断言用)。

bool xrtListValidate(const xlist* pList)

参数

参数方向约束说明
pList输入非空链表
返回值
返回含义失败时状态
true全部不变量成立—
false结构被破坏XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 公开结构损坏

范例已编译验证

containers/list_tour · 查询 · 观察

		!xrtListValidate(&List) ||

xrtListEmpty函数

返回链表是否为空。

bool xrtListEmpty(const xlist* pList)

参数

参数方向约束说明
pList输入非空链表
返回值
返回含义失败时状态
true无节点—
false非空纯查询
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 查询 · 观察

		!xrtListEmpty(&List) ||

xrtListCount函数

返回当前节点数量。

size_t xrtListCount(const xlist* pList)

参数

参数方向约束说明
pList输入非空链表
返回值
返回含义失败时状态
>= 0节点数—
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 查询 · 观察

		(xrtListCount(&List) != 0u) ||

xrtListFirst函数

返回首节点;空链表返回空指针。

xlistnode* xrtListFirst(const xlist* pList)

参数

参数方向约束说明
pList输入非空链表
返回值
返回含义失败时状态
非空首节点(借用)—
NULL空链表(正常结果)不设错
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list · 导航 · 观察

	for ( xlistnode* pNode = xrtListFirst(pCache);
		  pNode != NULL;
		  pNode = xrtListNext(pNode) ) {

xrtListLast函数

返回尾节点;空链表返回空指针。

xlistnode* xrtListLast(const xlist* pList)

参数

参数方向约束说明
pList输入非空链表
返回值
返回含义失败时状态
非空尾节点(借用)—
NULL空链表不设错
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 导航 · 观察

		(xrtListLast(&List) != NULL) ||

xrtListPrev函数

返回节点的前驱。

xlistnode* xrtListPrev(const xlistnode* pNode)

参数

参数方向约束说明
pNode输入非空、已连接节点
返回值
返回含义失败时状态
非空前驱—
NULL首节点或未连接不设错
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 导航 · 观察

		(xrtListPrev(&Entries[0].Node) != NULL) ||

xrtListNext函数

返回节点的后继。

xlistnode* xrtListNext(const xlistnode* pNode)

参数

参数方向约束说明
pNode输入非空、已连接节点
返回值
返回含义失败时状态
非空后继—
NULL尾节点或未连接不设错
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list · 导航 · 观察

		  pNode = xrtListNext(pNode) ) {

xrtListOwner函数

返回节点所属链表。

xlist* xrtListOwner(const xlistnode* pNode)

参数

参数方向约束说明
pNode输入非空、已连接节点
返回值
返回含义失败时状态
非空所属链表—
NULL未连接不设错
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 导航 · 观察

		(xrtListOwner(&Entries[2].Node) != &List) ||

xrtListContains函数

判断节点是否属于指定链表。

bool xrtListContains(const xlist* pList, const xlistnode* pNode)

参数

参数方向约束说明
pList输入非空链表
pNode输入非空节点
返回值
返回含义失败时状态
true属于—
false不属于或未连接不设错
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 查询 · 观察

	if ( !xrtListContains(&List, &Entries[2].Node) ||
		xrtListContains(&List, NULL) ||
		!xrtListLinked(&Entries[2].Node) ||
		xrtListLinked(&Detached.Node) ||
		(xrtListOwner(&Entries[2].Node) != &List) ||
		(xrtListOwner(NULL) != NULL) ||
		(xrtListPrev(&Entries[0].Node) != NULL) ||
		(xrtListPrev(&Entries[1].Node) != &Entries[0].Node) ||
		(xrtListNext(&Entries[4].Node) != NULL) ) {

xrtListLinked函数

判断节点是否已连接到任意链表。

bool xrtListLinked(const xlistnode* pNode)

参数

参数方向约束说明
pNode输入非空节点
返回值
返回含义失败时状态
true已连接—
false独立不设错
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 查询 · 观察

		!xrtListLinked(&Entries[2].Node) ||

xrtListPushFront函数

在链表首插入一个已初始化且未连接的节点。

bool xrtListPushFront(xlist* pList, xlistnode* pNode)

参数

参数方向约束说明
pList输入/输出非空、已初始化链表
pNode输入已 NodeInit、未连接节点
返回值
返回含义失败时状态
true已插入;Count +1—
false参数或状态错误链表不变
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 节点未初始化、已属于链表或不属于指定链表

范例已编译验证

containers/list · 编辑 · 观察

		if ( !xrtListPushFront(&Cache, &Items[i].Recent) ) {

xrtListPushBack函数

在链表尾插入一个已初始化且未连接的节点。

bool xrtListPushBack(xlist* pList, xlistnode* pNode)

参数

参数方向约束说明
pList输入/输出非空链表
pNode输入未连接节点
返回值
返回含义失败时状态
true已插入;Count +1—
false参数或状态错误链表不变
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 节点未初始化、已属于链表或不属于指定链表

范例已编译验证

containers/list_tour · 编辑 · 观察

	if ( !xrtListPushBack(&List, &Entries[1].Node) ||
		!xrtListInsertBefore(&List, &Entries[1].Node,
			&Entries[0].Node) ||
		!xrtListInsertAfter(&List, &Entries[1].Node,
			&Entries[2].Node) ||
		!xrtListPushBack(&List, &Entries[3].Node) ||
		!xrtListInsertAfter(&List, &Entries[3].Node,
			&Entries[4].Node) ||
		(xrtListCount(&List) != 5u) ||
		!exampleForwardText(&List, Text, sizeof(Text)) ||
		(strcmp(Text, "12345") != 0) ) {

xrtListInsertBefore函数

在参考节点之前插入未连接节点。

bool xrtListInsertBefore(xlist* pList, xlistnode* pPosition, xlistnode* pNode)

参数

参数方向约束说明
pList输入/输出非空链表
pPosition输入属于 pList参考节点
pNode输入未连接新节点
返回值
返回含义失败时状态
true已插入—
false参数或所有权错误链表不变
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 节点未初始化、已属于链表或不属于指定链表

范例已编译验证

containers/list_tour · 编辑 · 观察

		!xrtListInsertBefore(&List, &Entries[1].Node,
			&Entries[0].Node) ||

xrtListInsertAfter函数

在参考节点之后插入未连接节点。

bool xrtListInsertAfter(xlist* pList, xlistnode* pPosition, xlistnode* pNode)

参数

参数方向约束说明
pList输入/输出非空链表
pPosition输入属于 pList参考节点
pNode输入未连接新节点
返回值
返回含义失败时状态
true已插入—
false参数或所有权错误链表不变
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 节点未初始化、已属于链表或不属于指定链表

范例已编译验证

containers/list_tour · 编辑 · 观察

		!xrtListInsertAfter(&List, &Entries[1].Node,
			&Entries[2].Node) ||

xrtListRemove函数

从指定链表移除节点,但不释放节点内存;节点恢复独立状态可再插入。

bool xrtListRemove(xlist* pList, xlistnode* pNode)

参数

参数方向约束说明
pList输入/输出非空链表
pNode输入属于 pList节点
返回值
返回含义失败时状态
true已移除;Count -1—
false参数或所有权错误链表不变
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 节点未初始化、已属于链表或不属于指定链表

范例已编译验证

containers/list_tour · 编辑 · 观察

	if ( !xrtListRemove(&List, &Entries[3].Node) ||
		!xrtListPushBack(&List, &Entries[3].Node) ||
		!exampleForwardText(&List, Text, sizeof(Text)) ||
		(strcmp(Text, "354") != 0) ) {

xrtListPopFront函数

移除并返回首节点;空链表是正常结果。

xlistnode* xrtListPopFront(xlist* pList)

参数

参数方向约束说明
pList输入/输出非空链表
返回值
返回含义失败时状态
非空已脱离的首节点(独立状态)—
NULL空链表(正常结果)不设错
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 编辑 · 观察

		(xrtListPopFront(&List) != NULL) ||

xrtListPopBack函数

移除并返回尾节点;空链表是正常结果。

xlistnode* xrtListPopBack(xlist* pList)

参数

参数方向约束说明
pList输入/输出非空链表
返回值
返回含义失败时状态
非空已脱离的尾节点—
NULL空链表不设错
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 编辑 · 观察

		(xrtListPopBack(&List) != NULL) ) {

xrtListMoveFront函数

把已有节点移动到链表首,不改变节点数量。

bool xrtListMoveFront(xlist* pList, xlistnode* pNode)

参数

参数方向约束说明
pList输入/输出非空链表
pNode输入属于 pList节点
返回值
返回含义失败时状态
true已移动—
false参数或所有权错误链表不变
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 节点未初始化、已属于链表或不属于指定链表

范例已编译验证

containers/list · 编辑 · 观察

	if ( !xrtListMoveFront(&Cache, &Items[0].Recent) ) {

xrtListMoveBack函数

把已有节点移动到链表尾,不改变节点数量。

bool xrtListMoveBack(xlist* pList, xlistnode* pNode)

参数

参数方向约束说明
pList输入/输出非空链表
pNode输入属于 pList节点
返回值
返回含义失败时状态
true已移动—
false参数或所有权错误链表不变
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 节点未初始化、已属于链表或不属于指定链表

范例已编译验证

containers/list_tour · 编辑 · 观察

	if ( !xrtListMoveBack(&List, &Entries[0].Node) ||
		!exampleForwardText(&List, Text, sizeof(Text)) ||
		(strcmp(Text, "23451") != 0) ) {

xrtListClear函数

分离全部节点并保留可继续使用的空链表;各节点恢复独立状态。

bool xrtListClear(xlist* pList)

参数

参数方向约束说明
pList输入/输出非空链表
返回值
返回含义失败时状态
true已清空;Count 归零—
false参数或状态错误—
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 节点未初始化、已属于链表或不属于指定链表

范例已编译验证

containers/list · 编辑 · 观察

	if ( !xrtListClear(&Cache) ) {

xrtListIterBegin函数

启动正向迭代(升序)。

bool xrtListIterBegin(xlist* pList, xlistiter* pIterator)

参数

参数方向约束说明
pList输入非空链表
pIterator输出非空迭代器
返回值
返回含义失败时状态
true迭代器已就绪(空链表也可启动)—
false参数错误XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 迭代 · 观察

	if ( !xrtListIterBegin(&List, &Iter) ) {

xrtListIterRBegin函数

启动反向迭代(降序)。

bool xrtListIterRBegin(xlist* pList, xlistiter* pIterator)

参数

参数方向约束说明
pList输入非空链表
pIterator输出非空迭代器
返回值
返回含义失败时状态
true迭代器已就绪—
false参数错误XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空

范例已编译验证

containers/list_tour · 迭代 · 观察

	if ( !xrtListIterRBegin(&List, &Iter) ) {

xrtListIterNext函数

返回下一节点;自然结束不设置错误,外部结构修改会被拒绝。

xlistnode* xrtListIterNext(xlistiter* pIterator)

参数

参数方向约束说明
pIterator输入/输出非空、活动迭代器
返回值
返回含义失败时状态
非空下一节点—
NULL自然耗尽(不设错)或结构被修改结构被修改时 XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 迭代期间链表结构被外部修改

范例已编译验证

containers/list_tour · 迭代 · 观察

		while ( (pNode = xrtListIterNext(&Iter)) != NULL ) {

xrtListIterRemove函数

移除最近一次返回的节点,并让迭代器继续保持有效。

bool xrtListIterRemove(xlistiter* pIterator)

参数

参数方向约束说明
pIterator输入/输出非空、活动迭代器
返回值
返回含义失败时状态
true已移除(Count -1,迭代继续)—
false尚未取节点或已结束XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空
  • XERR_STATE — 当前轮尚未发布节点

范例已编译验证

containers/list_tour · 迭代 · 观察

		if ( !xrtListIterRemove(&Iter) ) {

xrtListIterEnd函数

提前结束迭代;允许传入空指针。

void xrtListIterEnd(xlistiter* pIterator)

参数

参数方向约束说明
pIterator输入允许空空 = 空操作
返回值
返回含义失败时状态
无借用状态已清除—
错误
  • 无 — 清理不失败

范例已编译验证

containers/list_tour · 迭代 · 观察

	xrtListIterEnd(&Iter);

常量索引常量

以下常量在本页所属头文件中定义,语义见公共头注释。

常量说明
XLIST_ERROR_ARGUMENT见头文件注释
XLIST_ERROR_MODIFIED见头文件注释
XLIST_ERROR_RANGE见头文件注释
XLIST_ERROR_STATE见头文件注释
XRT_CONTAINER_OF见头文件注释
XRT_LIST_INIT见头文件注释
XRT_LIST_NODE_INIT见头文件注释