list_entry剖析与验证

/*
&((type *)0)->member:   把“0”强制转化为指针类型,则该指针一定指向“0”(数据段基址)。因为指针是“type *”型的,
所以可取到以“0”为基地址的一个type型变量member域的地址。那么这个地址也就等于member域到结构体基地址的偏移字节数。   
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))):   
(char *)(ptr)使得指针的加减操作步长为一字节,(unsigned long)(&((type *)0)->member)等于ptr指向的member到该member所在结构体基地址的偏移字节数。
二者一减便得出该结构体的地址,转换为 (type *)型的指针。  */

#include <iostream>
#include <typeinfo>

using namespace std;

struct list_head {
    struct list_head *next;
    struct list_head *prev;
};


#define list_entry(ptr, type, member)					\
    ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

struct test_list
{
    int testdata;
    float testfloat;
    struct list_head list;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    struct test_list b;
    b.testdata = 5;
    b.testfloat = 11.2;

    struct test_list *pos = list_entry(&(b.testdata),struct test_list,testdata);

    cout << pos->testfloat << endl;

    return a.exec();
}

检查以下代码,有没有逻辑错误或者语法错误? /* 遍历检查ip是否被添加进了链表,已存在返回指针 不存在返回NULL */ LOCAL ARP_ENTRY* find_ip_in_list(IP_ADDR ip, struct list_head *head) { ARP_ENTRY *pEntry, *tmp; list_for_each_entry_safe(pEntry, tmp, &amp;g_arp_param.head_node, list) { if (pEntry-&gt;ip_n.ipAddr == ip.ipAddr) { return pEntry; } } return NULL; } /* 监听到ARP回应包处理,并添加条目 */ LOCAL void arp_respond_handle(int sock) { U8 raw_data[RAW_DATA_LEN_MAX]; U8 data_len = 0; char mac_str[STR_MAC_LEN] = {0}; char ip_str[STR_IP_LEN] = {0}; data_len = rev_raw_data (g_arp_param.arp_fd, raw_data, RAW_DATA_LEN_MAX); if (data_len &lt; 0) { ARP_ERROR(&quot;rev arp raw data %d fail!&quot;, g_arp_param.arp_fd); return; } ARP_PACKED *arp = (ARP_PACKED *)raw_data; /* 判断是不是合法的arp回复包 */ if ((ntohs(arp-&gt;ether_type) != ETH_P_ARP) || (ntohs(arp-&gt;op_code) != ARPOP_REPLY)) { return; } hex_to_mac(mac_str, STR_MAC_LEN, arp-&gt;mac_sender); inet_ntop(AF_INET, arp-&gt;ip_sender, ip_str, STR_IP_LEN); ARP_DEBUG(&quot;ip: %s --&gt; mac: %s&quot;, ip_str, mac_str); /* 检查该IP是否已经被添加过 */ IP_ADDR ip_src_n; ARP_ENTRY *p_entry = NULL; memcpy(ip_src_n.ipAddrByteFormat, arp-&gt;ip_sender, IP_ADDR_SIZE); p_entry = find_ip_in_list(ip_src_n, &amp;g_arp_param.head_node); if (NULL != p_entry) { /* 如果已存在,则只需要更新time */ p_entry-&gt;last_seen_s = time(NULL); return; } //Todo 把拿到的MAC地址和IP放入链表 /* 申请entry内存并插入链表尾部 */ p_entry = calloc(1,sizeof(ARP_ENTRY)); if (NULL == p_entry) { ARP_ERROR(&quot;calloc new arp_entry fail!&quot;); } list_add_tail(&amp;p_entry-&gt;list, &amp;g_arp_param.head_node); /* 填充新的entry */ p_entry-&gt;last_seen_s = time(NULL); memcpy(p_entry-&gt;ip_n.ipAddrByteFormat, arp-&gt;ip_sender, IP_ADDR_SIZE); memcpy(p_entry-&gt;mac, arp-&gt;mac_sender, MAC_ADDR_SIZE); } * 每一秒遍历检查设备是否超时 */ LOCAL void arp_valid_check_handle(void) { time_t now = time(NULL); ARP_ENTRY *pEntry, tmp; list_for_each_entry_safe(pEntry, tmp, &amp;g_arp_param.head_node, list) { if ((now - pEntry-&gt;last_seen_s) &gt; g_arp_param.config.period_valid_sec) { / 从链表删除 / list_del(&amp;pEntry-&gt;list); / 释放内存 */ free(pEntry); } } }
08-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值