推荐使用GetAdaptersAddresses API获取物理网卡MAC地址:先调用两次获取缓冲区大小并分配内存,遍历适配器链表时过滤未启用、环回、隧道接口及非6字节地址,再格式化输出十六进制MAC。

如果您在 Windows 平台上使用 C++ 开发网络相关程序,需要准确获取物理网卡的 MAC 地址,则可能遇到虚拟适配器干扰、地址长度不固定、接口未启用导致 PhysicalAddressLength 为 0 等问题。以下是解决此问题的步骤:
一、使用 GetAdaptersAddresses(推荐现代方式)
GetAdaptersAddresses 是 Windows Vista 及以后版本唯一官方推荐的 API,支持 IPv4/IPv6、可过滤未启用接口、能正确返回 Hyper-V、WSL2 等现代虚拟网卡的物理地址(若驱动提供),且避免了旧 API 的信息缺失缺陷。它通过 IP_ADAPTER_ADDRESSES 链表返回全部适配器信息,MAC 地址存储在 PhysicalAddress 字节数组中,长度由 PhysicalAddressLength 字段明确指示。
1、在源文件顶部包含头文件:#include
2、链接库:#pragma comment(lib, "Iphlpapi.lib") 或在项目设置中添加 Iphlpapi.lib
3、声明变量并首次调用以获取所需缓冲区大小:ULONG size = 0; GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &size);
4、分配足够内存并第二次调用:std::vector
5、遍历链表,跳过无效项:for (auto p = addr; p != nullptr; p = p->Next) { if (p->OperStatus != IfOperStatusUp || p->PhysicalAddressLength != 6 || p->IfType == IF_TYPE_SOFTWARE_LOOPBACK || p->IfType == IF_TYPE_TUNNEL) continue;
6、格式化输出 MAC 地址:printf("%02X-%02X-%02X-%02X-%02X-%02X\n", p->PhysicalAddress[0], p->PhysicalAddress[1], p->PhysicalAddress[2], p->PhysicalAddress[3], p->PhysicalAddress[4], p->PhysicalAddress[5]);
二、使用 GetAdaptersInfo(兼容旧系统方案)
GetAdaptersInfo 是 Windows 2000 起提供的遗留 API,仅支持 IPv4 接口,不识别 IPv6-only 适配器、Hyper-V vSwitch、部分容器网络接口,且 Address 字段仅预留 8 字节空间,易发生截断或全零输出。适用于必须兼容 Windows XP 的极少数场景,但需主动规避其已知缺陷。
1、包含头文件:#include
2、链接库:pragma comment(lib, "Iphlpapi.lib")
3、首次调用获取缓冲区大小:ULONG bufferSize = 0; GetAdaptersInfo(nullptr, &bufferSize);
4、分配内存并重试:PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)malloc(bufferSize); GetAdaptersInfo(pAdapterInfo, &bufferSize);
5、遍历适配器链表,校验类型与地址有效性:while (pAdapterInfo) { if ((pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET || pAdapterInfo->Type == IF_TYPE_IEEE80211) && pAdapterInfo->AddressLength == 6) {
6、提取并格式化 MAC:for (int i = 0; i Address[i], i
三、解析 ipconfig /all 命令输出(辅助验证方案)
该方法不依赖 API 调用,而是启动子进程执行系统命令并解析标准输出,适用于调试、日志比对或无法链接 Iphlpapi.lib 的受限环境。其本质是文本匹配,稳定性低于原生 API,且需处理多语言系统下“物理地址”字段名本地化问题(如中文系统为“物理地址”,英文为“Physical Address”)。
1、构造命令行字符串:std::string cmd = "ipconfig /all > temp_ipconfig.txt";
2、执行命令并等待完成:system(cmd.c_str());
3、以只读方式打开生成的临时文件:std::ifstream file("temp_ipconfig.txt");
4、逐行读取,查找含“物理地址”或“Physical Address”的行:std::string line; while (std::getline(file, line)) { if (line.find("物理地址") != std::string::npos || line.find("Physical Address") != std::string::npos) {
5、提取冒号后内容并去除空格与换行:size_t pos = line.find(':'); if (pos != std::string::npos) { std::string macPart = line.substr(pos + 1); macPart.erase(0, macPart.find_first_not_of(" \t")); macPart.erase(macPart.find_last_not_of(" \t") + 1);
6、输出清洗后的 MAC 字符串:std::cout
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











