getadaptersaddresses(windows)、getifaddrs(linux)、sysctl+getifaddrs(macos)是各平台获取mac地址最稳定方式,需分别处理缓冲区重分配、af_packet/af_link类型判断及物理地址偏移,跨平台时须统一格式化、处理权限与快照局限。

Windows平台用GetAdaptersAddresses获取MAC地址
在Windows上,GetAdaptersAddresses 是最稳定、推荐的方式,它能绕过老旧的GetAdaptersInfo(已弃用且不支持IPv6适配器)。调用前必须链接Iphlpapi.lib,并确保WINVER ≥ 0x0600(即XP SP2+)。常见错误是传入缓冲区太小导致返回ERROR_BUFFER_OVERFLOW,此时需按返回值重新分配内存。
关键步骤:
- 先调用一次
GetAdaptersAddresses传NULL缓冲区,获取所需缓冲区大小 - 用
malloc或std::vector<byte></byte>分配对应大小内存 - 第二次调用填入该缓冲区,遍历
IP_ADAPTER_ADDRESSES链表 - 每个节点的
PhysicalAddress字段即MAC地址,长度由PhysicalAddressLength给出(通常为6)
注意:部分虚拟网卡或禁用的适配器可能PhysicalAddressLength == 0,应跳过;OperStatus != IfOperStatusUp的适配器MAC虽存在但不可用,按需过滤。
Linux用getifaddrs遍历接口获取AF_PACKET地址
Linux下标准做法是getifaddrs,但必须注意:MAC地址藏在AF_PACKET类型的sockaddr_ll结构里,不是AF_INET或AF_INET6。很多初学者误读ifa_addr字段,结果拿到IP地址而非MAC。
实操要点:
- 调用
getifaddrs(&ifaddr)后遍历链表 - 检查
ifa_addr->sa_family == AF_PACKET(不是AF_INET) - 强转
struct sockaddr_ll*,取sll_addr字段,长度为sll_halen(通常6) - 记得
freeifaddrs(ifaddr)释放内存,否则泄漏
兼容性提示:某些嵌入式系统或旧内核可能不支持AF_PACKET,可fallback到读取/sys/class/net/*/address文件,但需注意权限和符号链接问题。
macOS用sysctl获取IFMIB_IFDESCR对应的ifma_lladdr
macOS没有getifaddrs的AF_PACKET支持,也不能直接用ioctl(SIOCGIFHWADDR)(已被废弃)。正确路径是用sysctl查net.ifmib MIB,再结合ifaddrs获取链路层地址。
核心逻辑:
- 用
sysctlbyname("net.link.generic.system", ...)确认链路层支持 - 调用
getifaddrs(&ifaddr),对每个接口查ifa_addr->sa_family - 若为
AF_LINK,强转为struct sockaddr_dl*,从sdl_data + sdl_nlen偏移处读MAC(sdl_alen为长度) -
sdl_type为IFT_ETHER才认为是真实以太网卡,过滤掉IFT_LOOP等
容易踩的坑:macOS的sockaddr_dl结构中MAC起始位置不固定,必须用sdl_nlen跳过接口名长度,否则读错字节。
跨平台封装要注意的三个硬伤
真正写跨平台代码时,光拼凑各系统API不够——有三个地方几乎必然出错:
- MAC地址格式:Windows/Linux/macOS都返回原始字节数组,但输出时有人习惯
"%02x:%02x:...",有人要大写或无分隔符,统一用std::format(C++20)或std::stringstream处理,别手写sprintf - 权限问题:Linux/macOS下非root用户可能无法读取某些虚拟接口(如Docker桥接),
getifaddrs仍会返回但AF_LINK数据可能为空,需检查ifam_addrs是否有效 - 热插拔响应:上述所有API都是快照式调用,无法监听网卡增删。真需要实时更新,Windows得用WMI或NDIS通知,Linux用
netlinksocket,macOS靠KQueue监听/dev/bpf*——这些远超“获取列表”范畴,别试图用轮询假装实时
实际项目里,如果只要启动时初始化一次MAC列表,老老实实用各平台原生API最稳;但凡涉及动态网络拓扑,就得承认这是操作系统层的事,应用层不该硬扛。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











