USB开发涉及到libusb,看了下源码,现在已经到了1.0.23版;全部用的C,编译器和平台的普适性相对比较强;
其中的list_head作为关键链表,也是各个链接结构的成员(member)变量。而利用这个成员变量完成各个结构链接,涉及到几个很有意思的宏,其中包括list_entry,list_for_each_entry,这种用法和我们最普通的用法有点区别:在C ++中,通常我用标准std::list, std::vector实现;在C中,我们往往直接使用结构自自身的指针来完成链接,而不是使用这种成员链接指针(list_head)。
写了个list_entry应用原理的解析,用3种完全等价的方式找到:dev->session_data == 2
#include
struct list_head {
struct list_head* prev, * next;
};
/* Get an entry from the list
* ptr - the address of this list_head element in "type"
* type - the data type that contains "member"
* member - the list_head element in "type"
*/
#define list_entry(ptr, type, member) \
((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/* Get each entry from a list
* pos - A structure pointer has a "member" element
* head - list head
* member - the list_head element in "pos"
* type - the type of the first parameter
*/
#define list_for_each_entry(pos, head, member, type) \
for (pos = list_entry((head)->next, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, type, member))
#define list_for_each_entry_safe(pos, n, head, member, type) \
for (pos = list_entry((head)->next, type, member), \
n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, type, member))
#define list_empty(entry) ((entry)->next == (entry))
struct libusb_device {
int refcnt;
uint8_t bus_number;
uint8_t port_number;
struct libusb_device* parent_dev;
uint8_t device_address;
uint8_t num_configurations;
struct list_head list;
unsigned long session_data;
};
libusb_device* list_entry_func(list_head* ptr) {
uintptr_t upt = offsetof(libusb_device, list);
upt = (uintptr_t)(ptr) - upt;
return (libusb_device*)(upt);
}
int main() {
libusb_device ld1;
libusb_device ld2;
libusb_device ld3;
ld1.list.next = &ld2.list;
ld2.list.prev = &ld1.list;
ld2.list.next = &ld3.list;
ld3.list.prev = &ld2.list;
ld1.session_data = 1;
ld2.session_data = 2;
ld3.session_data = 3;
struct list_head usb_devs;
usb_devs.next = &ld1.list;
usb_devs.prev = &ld3.list;
struct libusb_device* dev;
struct libusb_device* ret = NULL;
//#define list_entry(ptr, type, member) \
//((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
//#define list_first_entry(ptr, type, member) \
//list_entry((ptr)->next, type, member)
//#define list_for_each_entry(pos, head, member, type) \
//for (pos = list_entry((head)->next, type, member); \
// &pos->member != (head); \
// pos = list_entry(pos->member.next, type, member))
list_for_each_entry(dev, &usb_devs, list, struct libusb_device)
if (dev->session_data == 2) {
std::cout list.next)) {
if (dev->session_data == 2) {
std::cout list.next, libusb_device, list))
if (dev->session_data == 2) {
std::cout
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?