我附上这个问题的代码应该获取设备的mac地址并打印出来。当我将结构ifreq中的数据复制到uint8_t数组时,它可以工作,但是当我没有,我得到奇怪的结果。查看第二行和输出的第二个字节。
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <net/ethernet.h>
#include <sys/types.h>
#include <stdint.h>
int main()
{
uint8_t tab[6];
int i;
struct ifreq one;
int sd = socket(AF_PACKET, SOCK_RAW, 0);
memset(&one, 0, sizeof(struct ifreq));
strcpy(one.ifr_name, "eth0");
int v = ioctl(sd, SIOCGIFHWADDR, &one);
memcpy(tab, one.ifr_hwaddr.sa_data, sizeof(uint8_t) * 6);
for(i=0;i<6;i++)
printf("%02x:", tab[i]);
printf("\n");
for(i=0;i<6;i++)
printf("%02x:", one.ifr_hwaddr.sa_data[i]);
printf("\n");
}
输出:
74:86:7A:0A:2C:6D:
74:ffffff86:7A:0A:2C:6D:
答案 0 :(得分:4)
您是否在问为什么第二个字节打印为ffffff86
而不是86
?这是因为它已被签名延长。 one.ifr_hwaddr.sa_data[i]
数组被声明为有符号字符数组,但是tab []数组是无符号的。
printf的args都被提升为int。无符号字符0x86被提升为0x00000086,但是当假定相同的值被签名时,它将被提升为0xFFFFFF86。
答案 1 :(得分:1)
整体推广再次爆发!
由于转化说明符"x"
同时使用了printf
行和unsigned int
。
要打印signed
或unsigend
int
的一半(假设为32位整数),请使用length modifer "h"
两次:
printf("%02hhx:", one.ifr_hwaddr.sa_data[i]);
答案 2 :(得分:0)
在一种情况下,您可以指定促销的方式。在第二种情况下,你不是。您需要促销未签名。因此,不指定它是如何发生的,会导致问题。
如果字节是0x8f,则需要提升该值,就好像该类型是无符号的一样。否则,保留该值需要保留符号位。
促销使价值保持不变。因此,当原始位在被提升时被解释为一个值时,它会产生巨大的差异。
答案 3 :(得分:0)
我怀疑,one.ifr_hwaddr.sa_data是字符数组 在这种情况下,char表示签名字符。
因此,当通过printf的变量参数列表传递时,它被提升为int,printf将其打印为unsigned int(&#34; x&#34;说明符)
当从char提升为int时,编译器的目标是保留其值 - 而不是其二进制表示。
0x86是十进制的134,被视为unsigned char和-122,被视为signed char。
134 as unsigned int表示为0x68 -122 as int表示为0xffffff86(-1表示int为0xffffffff)
因此,打印0xffffff86。 在这种情况下(打印二进制为十六进制)我使用%02hhx printf说明符 %hhx告诉printf将其视为unsigned char - 只有1个字节。