linux内核链表

/*********************************************************************************************
    *  @Copyright (c) , All rights reserved.
    *  @file:       ListHead.hpp
    *  @version:    ver 1.0
    *  @author:     闹闹
    *  @brief:  
    *  @change:
    *  @email: 	1319144981@qq.com
    *  Date             Version    Changed By      Changes 
    *  2021/5/10 9:49:00    1.0       闹闹            create
	写一句自己最喜欢的话吧。
	为天地立心,为生民立命,为往圣继绝学,为万世开太平。
**********************************************************************************************/
/**********************************************************************************************
* modify_author:			闹闹
* modify_time:      2021/5/10 13:05:53
* modify_content:	
* modify_reference:
* modify_other:
参考链接:  https://blog.csdn.net/dijkstar/article/details/19249219
			https://blog.csdn.net/weixin_40746176/article/details/100530190
			https://blog.csdn.net/u014453898/article/details/53741921
			https://blog.csdn.net/szullc/article/details/86565368
使用方法:	https://blog.csdn.net/wanshilun/article/details/79747710
* modify_version:   1.0.0.2
**********************************************************************************************/
#pragma once
#ifndef __LISTHEAD_H__
#define __LISTHEAD_H__
#define LIST_POISON1  ((void *) 0x00100100)
#define LIST_POISON2  ((void *) 0x00200200)
#ifndef ARCH_HAS_PREFETCH
#define ARCH_HAS_PREFETCH
static inline void prefetch(const void *x) { ; }
static inline void prefetchw(const void *x) { ; }
#endif
/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    定义一个结构体,只含有表示前驱和后继的指针,它就是我们的主角了
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
struct list_head {
	struct list_head *next, *prev;
};
/******************************************************************************
* @FuncName:  
* @Author:    闹闹
* @Brief:     静态初始化
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter: 
* @OutputParameter: 
* @Returns:   
* @Others:    
******************************************************************************/
#define LIST_HEAD_INIT(name){&(name),&(name)}
#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

//
//#ifndef offsetof
//#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
//#endif
//#define container_of(ptr, type, member) ({          \
//    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
//    (type *)( (char *)__mptr - offsetof(type,member) );})

#define INIT_LIST_HEAD(listPtr) do{\
	(listPtr)->next = (listPtr); (listPtr)->prev = (listPtr);\
}while(0)

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    将一个元素插入到两个元素之间, 即将 new插入到prev和next中, 这个函数是下面在头部和尾部插入的实现基础
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void __list_add(struct list_head *newptr,struct list_head *prev,struct list_head *next){
	// 前后向指针的改写赋值
	next->prev = newptr;
	newptr->next = next;
	newptr->prev = prev;
	prev->next = newptr;
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:     在头部插入,在头指针和第一个元素间插入,
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter: newptr  新指针  head 链表头指针
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void list_add(struct list_head *newptr, struct list_head *head){
	__list_add(newptr, head, head->next);
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    在尾部插入,在最后一个元素间和头指针间插入, 因为是循环链表嘛~
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter: newptr  新指针  head 链表头指针
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void list_add_tail(struct list_head *newptr, struct list_head *head){
	__list_add(newptr, head->prev, head);
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    删除两个元素之间的元素~
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void __list_del(struct list_head * prev, struct list_head * next){
	next->prev = prev;
	prev->next = next;
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    删除一个已知元素entry
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void list_del(struct list_head *entry){
	__list_del(entry->prev, entry->next);
	entry->next = (list_head *)LIST_POISON1;
	entry->prev = (list_head *)LIST_POISON2;
}

static inline void list_del_init(struct list_head *entry){
	__list_del(entry->prev, entry->next);
	INIT_LIST_HEAD(entry);
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    指针的变换
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void list_replace(struct list_head *old,struct list_head *newptr){
	newptr->next = old->next;
	newptr->next->prev = newptr;
	newptr->prev = old->prev;
	newptr->prev->next = newptr;
}

static inline void list_replace_init(struct list_head *old,struct list_head *newptr){
	list_replace(old, newptr);
	INIT_LIST_HEAD(old);
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    将一个元素list 移动到另一个链表的head的头部
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void list_move(struct list_head *list, struct list_head *head){
	// 从原处的list后摘掉
	__list_del(list->prev,list->next);
	// 添加到新链表的头部
	list_add(list, head);
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    将一个元素list 移动到另一个链表head的队尾
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void list_move_tail(struct list_head *list,struct list_head *head){
	// 从原处的list后摘掉
	__list_del(list->prev,list->next);
	// 添加到新链表的队尾
	list_add_tail(list, head);
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    链表是否为空
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline int list_empty(struct list_head *head){
	return head->next == head;
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    list 是否为最后一个元素
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline int list_is_last(const struct list_head *list, const struct list_head *head){
	return list->next == head;
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    检查链表是否为空并且没有被改变
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline int list_empty_careful(const struct list_head *head){
	struct list_head *next = head->next;
	return (next == head) && (next == head->prev);
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    拆分操作, 将一个队列由指定的位置拆成两个队列
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others: list是新队列的head指针, 包括的元素从原head队列的第一个元素到entry, head队列仅包括余下的元素
******************************************************************************/
static inline void __list_cut_position(struct list_head *list,struct list_head *head, struct list_head *entry){
	struct list_head *new_first = entry->next;
	list->next = head->next;
	list->next->prev = list;
	list->prev = entry;
	entry->next = list;
	head->next = new_first;
	new_first->prev = head;
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    将list列表中除了list当前节点本身的其余部分,插入到prev和next之间
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others: 
******************************************************************************/
static inline void __list_splice(const struct list_head *list,struct list_head *prev){
	struct list_head *first = list->next;
	struct list_head *last = list->prev;
	struct list_head *at = prev->next;

	first->prev = prev;
	prev->next = first;

	last->next = at;
	at->prev = last;
}
/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    将一个列表插入到另一个列表的头部
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void list_splice(struct list_head *list,struct list_head *head){
	if (!list_empty(list))
		__list_splice(list, head);
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:   连接两个列表并重新初始化清空的列表。
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static  void list_splice_init(struct list_head *list,struct list_head *head){
	if (!list_empty(list)) {
		__list_splice(list, head);
		INIT_LIST_HEAD(list);
	}
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    将一个列表插入到另一个列表的尾部
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
static inline void list_splice_tail(struct list_head *list,struct list_head *head){
	if (!list_empty(list))
		__list_splice(list, head->prev);
}

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    得到链表中的对象
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
******************************************************************************/
#define list_entry(ptr, type, member) \
   ((type *)((char *)(ptr)-(size_t)(&((type *)0)->member)))



/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:   得到链表第一个元素
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_first_entry - get the first element from a list
* @ptr:    the list head to take the element from.
* @type:   the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
******************************************************************************/
#define list_first_entry(ptr, type, member) \
    list_entry((ptr)->next, type, member)


/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    链表遍历,从前向后
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each	-	iterate over a list
* @pos:	the &struct list_head to use as a loop counter.
* @head:	the head for your list.
******************************************************************************/
#define list_for_each(pos, head) \
	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
        	pos = pos->next, prefetch(pos->next))

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    链表遍历,从前向后
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* __list_for_each  -   iterate over a list
* @pos:    the &struct list_head to use as a loop cursor.
* @head:   the head for your list.
*
此变体与list_for_each()的不同之处在于它是最简单的列表迭代代码,不需要预取。对于知道列表非常短(空)的代码,使用此选项比上式减少很多时间。
******************************************************************************/
#define __list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    链表遍历,从后向前
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_prev	-	iterate over a list backwards
* @pos:	the &struct list_head to use as a loop counter.
* @head:	the head for your list.。
******************************************************************************/
#define list_for_each_prev(pos, head) \
	for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
        	pos = pos->prev, prefetch(pos->prev))

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    链表遍历,从后向前,对列表进行迭代,以防向后删除列表项
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_prev_safe   -   iterate over a list safe against removal of list entry backwards
* @pos:    the &struct list_head to use as a loop cursor.
* @n:      another &struct list_head to use as temporary storage
* @head:   the head for your list.
******************************************************************************/
#define list_for_each_prev_safe(pos, n, head) \
    for (pos = (head)->prev, n = pos->prev; prefetch(pos->prev), pos != (head); \
            pos =n, n = pos->prev)

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    链表遍历,从前向后,对列表进行迭代以防止删除列表项
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_safe	-	iterate over a list safe against removal of list entry
* @pos:	the &struct list_head to use as a loop counter.
* @n:		another &struct list_head to use as temporary storage
* @head:	the head for your list.
******************************************************************************/
#define list_for_each_safe(pos, n, head) \
	for (pos = (head)->next, n = pos->next; pos != (head); \
		pos = n, n = pos->next)

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    链表遍历,从前向后,迭代给定类型的列表
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_entry	-	iterate over list of given type
* @pos:	the type * to use as a loop counter.
* @head:	the head for your list.
* @member:	the name of the list_struct within the struct.
******************************************************************************/
#define list_for_each_entry(pos, head, member)				\
	 for (pos = list_entry((head)->next, typeof(*pos), member);  \
             prefetch(pos->member.next), &pos->member != (head);    \
             pos = list_entry(pos->member.next, typeof(*pos), member))

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    链表遍历,从后向前,迭代给定类型的列表
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos:    the type * to use as a loop cursor.
* @head:   the head for your list.
* @member: the name of the list_struct within the struct.
******************************************************************************/
#define list_for_each_entry_reverse(pos, head, member)          \
        for (pos = list_entry((head)->prev, typeof(*pos), member);  \
             prefetch(pos->member.prev), &pos->member != (head);    \
             pos = list_entry(pos->member.prev, typeof(*pos), member))


/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    为每个项目准备一个pos条目,以便在列表中使用list_for_each_entry_continue()
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos:    the type * to use as a start point
* @head:   the head of the list
* @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
******************************************************************************/
#define list_prepare_entry(pos, head, member) \
            ((pos) ? : list_entry(head, typeof(*pos), member))


/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:    继续迭代给定类型列表
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_entry_continue - continue iteration over list of given type
* @pos:    the type * to use as a loop cursor.
* @head:   the head for your list.
* @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
******************************************************************************/
#define list_for_each_entry_continue(pos, head, member)         \
            for (pos = list_entry(pos->member.next, typeof(*pos), member);  \
                 prefetch(pos->member.next), &pos->member != (head);    \
                 pos = list_entry(pos->member.next, typeof(*pos), member))

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:   从当前点迭代给定类型的列表
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos:    the type * to use as a loop cursor.
* @head:   the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
******************************************************************************/
#define list_for_each_entry_from(pos, head, member)             \
            for (; prefetch(pos->member.next), &pos->member != (head);  \
                 pos = list_entry(pos->member.next, typeof(*pos), member))

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:   从当前点迭代给定类型的列表,迭代给定类型的列表,以防止删除列表项
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos:	the type * to use as a loop counter.
* @n:		another type * to use as temporary storage
* @head:	the head for your list.
* @member:	the name of the list_struct within the struct.
******************************************************************************/
#define list_for_each_entry_safe(pos, n, head, member)			\
	for (pos = list_entry((head)->next, typeof(*pos), member),	\
		n = list_entry(pos->member.next, typeof(*pos), member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:   迭代给定类型的列表,在当前点之后继续,防止删除列表条目。
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_entry_safe_continue
* @pos:    the type * to use as a loop cursor.
* @n:      another type * to use as temporary storage
* @head:   the head for your list.
* @member: the name of the list_struct within the struct.
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
******************************************************************************/
#define list_for_each_entry_safe_continue(pos, n, head, member)         \
            for (pos = list_entry(pos->member.next, typeof(*pos), member),      \
                n = list_entry(pos->member.next, typeof(*pos), member);     \
                 &pos->member != (head);                        \
                 pos = n, n = list_entry(n->member.next, typeof(*n), member))


/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:  从当前点遍历给定类型的列表删除列表条目。
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_entry_safe_from
* @pos:    the type * to use as a loop cursor.
* @n:      another type * to use as temporary storage
* @head:   the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
******************************************************************************/
#define list_for_each_entry_safe_from(pos, n, head, member)             \
                    for (n = list_entry(pos->member.next, typeof(*pos), member);        \
                         &pos->member != (head);                        \
                         pos = n, n = list_entry(n->member.next, typeof(*n), member))

/******************************************************************************
* @FuncName:
* @Author:    闹闹
* @Brief:  向后迭代给定类型的列表,防止删除列表条目的数目。
* @Version:   1.0.0.1
* @Date:	  2021/5/10 9:56
* @InputParameter:
* @OutputParameter:
* @Returns:
* @Others:
* list_for_each_entry_safe_reverse
* @pos:    the type * to use as a loop cursor.
* @n:      another type * to use as temporary storage
* @head:   the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
******************************************************************************/
#define list_for_each_entry_safe_reverse(pos, n, head, member)      \
                        for (pos = list_entry((head)->prev, typeof(*pos), member),  \
                            n = list_entry(pos->member.prev, typeof(*pos), member); \
                             &pos->member != (head);                    \
                             pos = n, n = list_entry(n->member.prev, typeof(*n), member))

#endif  //__LISTHEAD_H__
/************************ (C) COPYRIGHT LEI *****END OF FILE****/

example

#include "stdio.h"
#include <stdlib.h>
#include <string.h>
#include "ListHead.hpp"

//自定义的数据结构
struct list_test_struct
{
	struct list_head	list;

	int key;
	int data;
};

void main()
{
	struct list_head list = { 0 };  //定义链表(头) 
	struct list_head *pos = NULL;
	struct list_head *n = NULL;

	int i = 0;

	printf("定义链表\n");

	printf("初始化链表!\r\n");
	INIT_LIST_HEAD(&list);  //初始化链表(头尾相接,形成空链表循环) 

							//判断链表是否为空 
	printf("判断链表是否为空:");
	if (list_empty(&list)) {
		printf("空\r\n");
	}
	else {
		printf("非空\r\n");
	}

	//批量添加节点 
	printf("批量添加节点:\r\n");
	for (i = 0; i < 10; i++)
	{
		int key = i;    //key 
		int data = i * 10;  //data 

		struct list_test_struct *st = (struct list_test_struct*)malloc(sizeof(struct list_test_struct));
		st->key = key;
		st->data = data;
		list_add(&st->list, &list);
	}

	//显示列表所有节点 
	printf("显示列表所有节点:\r\n");
	list_for_each(pos, &list)
	{
		struct list_test_struct *st = list_entry(pos, struct list_test_struct, list);
		printf("\t node:key(%d),data(%d)\r\n", st->key, st->data);
	}

	//释放所有节点资源 
	printf("释放所有节点资源!\r\n");
	list_for_each_safe(pos, n, &list)
	{
		struct list_test_struct *st = list_entry(pos, struct list_test_struct, list);
		list_del(pos);  //删除节点,删除节点必须在删除节点内存之前 
		free(st);   //释放节点内存 
	}

	system("psuse");

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值