繁体   English   中英

奇怪的printf()行为

[英]Strange printf() behavior

我附带此问题的代码应获取设备的mac地址并打印出来。 当我将数据从struct 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");
}

OUTPUT:

74:86:7A:0A:2C:6D:

74:ffffff86:7A:0A:2C:6D:

您是在问为什么第二个字节打印为ffffff86而不是86吗? 这是因为它已被符号扩展。 one.ifr_hwaddr.sa_data[i]数组声明为有符号字符的数组,但是您的tab []数组是无符号的。

将printf的arg都提升为int。 无符号字符0x86提升为0x00000086,但是当假定对相同的值进行签名时,它将提升为0xFFFFFF86。

整数提升再次来袭!

由于使用了转换说明符"x"所以两行都printf了一个unsigned int

要打印有signed或无unsigend int的一半(假设32bit int),请使用长度修饰符"h"两次:

printf("%02hhx:", one.ifr_hwaddr.sa_data[i]);

在一种情况下,您可以指定促销的方式。 在第二种情况下,您不需要。 您需要取消促销。 因此,不指定其发生方式会导致问题。

如果字节为0x8f,则需要将该值提升为无符号类型。 否则,保留该值需要保留符号位。

促销使价值保持不变。 因此,当原始位提升时如何将原始位解释为值会产生巨大差异。

我怀疑one.ifr_hwaddr.sa_data是字符数组。在这种情况下,字符表示已签名字符。

因此,当通过printf的变量参数列表传递时,它被提升为int,并且printf将其打印为unsigned int(“ x”说明符)

从char提升为int时,编译器的目标是保留其值-而不是其二进制表示形式。

0x86是134(十进制),被视为无符号字符,而-122,被视为有符号字符。

134表示为无符号int表示为0x68 -122表示int表示为0xffffff86(-1表示int为0xffffffff)

因此,将打印0xffffff86。 在这种情况下(将二进制打印为十六进制),我使用%02hhx printf说明符%hhx告诉printf将其视为无符号字符-仅具有1个字节。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM