用16进制形式输出有符号数的小问题

当使用signed char类型读取16进制数0xFF并以%02x格式通过printf输出时,结果变为0xFFFFFFFF。原因在于有符号数的扩展和printf的格式要求,导致了从8位的-1(0xFF)到32位无符号数(0xFFFFFFFF)的转换。
摘要由CSDN通过智能技术生成

问题

昨天在写代码的过程中,遇到了这样一个东西:
用一个signed char类型的变量读取一个16进制数0xFF,然后再将其用printf输出成%02x的形式,最后的输出结果是:FFFFFFFF

DEMO程序如下:


#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fp;
    signed char temp = 0;
    int t = 0xff;           //unsigned int和signed int不影响结果
    fp = fopen("test.data", "wb");
    fwrite(&t, 1, 1, fp);
    fclose(fp);
    fp = fopen("test.data", "rb");
    fscanf(fp, "%c", &temp);
    fclose(fp);
    printf("%02x\n", temp);
    return 0;
}  

如上程序,signed char型的变量temp以二进制形式读取数据0xff,然后用printf以十六进制形式输出,最后输出了0xffffffff。

分析原因

首先signed char型是8位,temp以二进制形式读取0xff,由于其是有符号数,所以其是一个负数(-1)。然后到printf中以十六进制输出,由于printf中的格式化字符串%x要求输出数据类型为无符号16进制整数,且%x对应数据类型为unsigned int,因此temp首先进行有符号扩展,从signed char(0xff即8位-1)到signed int(0xffffffff,即32位的-1),再做无符号扩展,从signed int到unsigned int(0xffffffff,即32位的无符号数ffffffff)。
以上的分析都可以根据printf的源码得到,点击到源码链接

附:printf源码

/* -*- linux-c -*- ----------------------------------------
 *
 * Copyright (C) 1991, 1992 Linus Torvalds
 * Copyright 2007 rPath, Inc. - All Rights Reserved
 *
 * This file is part of the Linux kernel, and is made available under
 * the terms of the GNU General Public License version 2.
 ------------------------------------------------------- */

/*
 * Oh, it's a waste of space, but oh-so-yummy for debugging. This
 * version of printf() does not include 64-bit support. "Live with
 * it."
 *
 */

#include "boot.h"

static int skip_atoi(const char **s)
{
    int i = 0;

    while (isdigit(**s))
        i = i * 10 + *((*s)++) - '0';
    return i;
}

#define ZEROPAD    1        /* pad with zero */
#define SIGN    2        /* unsigned/signed long */
#define PLUS    4        /* show plus */
#define SPACE    8        /* space if plus */
#define LEFT    16        /* left justified */
#define SMALL    32        /* Must be 32 == 0x20 */
#define SPECIAL    64        /* 0x */

#define __do_div(n, base) ({ \
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值