You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何sscanf解析uint16_t类型变量a时结果为0?

问题:uint16_t变量转十六进制字符串后转回十进制值为0

我尝试将一系列十进制数转换为十六进制字符串,再转回十进制数(复杂业务场景的简化模型)。现有代码中其余变量转换均正常,但uint16_t类型变量a转回后的值为0(预期应为43),相关代码如下:

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

int main(void)
{
    /********************* A *******************/
    uint16_t a = 43;   //0x002b 
    int16_t  b = -43;  //0xffd5
    uint32_t c = 234;  //0x000000ea
    int32_t d = -234;  //0xffffff16

    char aStr[10]={0};
    char bStr[10]={0};
    char cStr[10]={0};
    char dStr[10]={0};

    snprintf(aStr, sizeof(aStr), "%04hhx", a);
    snprintf(bStr, sizeof(bStr), "%04x", b & 0xFFFF);
    snprintf(cStr, sizeof(cStr), "%08hhx", c);
    snprintf(dStr, sizeof(aStr), "%08x", d & 0xFFFFFFFF);

    fprintf(stdout, "TX a = %s.\n", aStr);
    fprintf(stdout, "TX b = %s.\n", bStr);
    fprintf(stdout, "TX c = %s.\n", cStr);
    fprintf(stdout, "TX d = %s.\n", dStr);

    /********************* B *******************/

    uint16_t aOut = 0;
    int16_t bOut = 0;
    uint32_t cOut = 0;
    int32_t dOut = 0;

    sscanf(aStr, "%04hhx", &aOut);
    sscanf(bStr, "%04x", &bOut);
    sscanf(cStr, "%08hhx", &cOut);
    sscanf(dStr, "%08x", &dOut);

    fprintf(stdout, "rx a = %d\n", aOut);  //<---- 此处输出0,原因是什么?
    fprintf(stdout, "rx b = %d\n", bOut);
    fprintf(stdout, "rx c = %d\n", cOut);
    fprintf(stdout, "rx d = %d\n", dOut);

    return 0;
}

问题原因分析

1. 格式符与变量类型不匹配(核心问题)

  • 生成字符串阶段:snprintf(aStr, sizeof(aStr), "%04hhx", a)中,%hhx是专门用于输出unsigned char(8位无符号字符)类型的格式符,但a是uint16_t(16位无符号整数)。虽然a=43小于256,截断后输出的002b看似正确,但这属于错误用法,若a的值超过255,结果会被错误截断。
  • 解析字符串阶段:sscanf(aStr, "%04hhx", &aOut)中,%hhx要求传入unsigned char*类型的指针,但实际传入的是uint16_t*类型的&aOut,这直接导致类型不匹配,触发C语言中的未定义行为。sscanf会尝试将解析到的值写入unsigned char大小的内存空间,而uint16_t占用2字节,这可能只修改了aOut的部分字节,或因指针类型错误导致写入位置异常,最终结果为0。

2. 未使用固定宽度整数的标准格式宏

代码中引入了<inttypes.h>头文件,但未使用其中提供的标准格式宏(如PRIx16用于输出uint16_t的十六进制,SCNx16用于输入),而是使用了依赖于系统类型大小的hhx、hx等格式符,既降低了代码可移植性,也容易引发类型匹配错误。

额外问题:uint32_t变量c的处理同样存在错误

snprintf(cStr, sizeof(cStr), "%08hhx", c)中的%hhx同样会将uint32_t类型的c截断为unsigned char,若c的值超过255,输出结果会完全错误。

修复方案

针对uint16_t和uint32_t的格式符进行修正,使用匹配的格式符或标准宏:

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

int main(void)
{
    /********************* A *******************/
    uint16_t a = 43;   //0x002b 
    int16_t  b = -43;  //0xffd5
    uint32_t c = 234;  //0x000000ea
    int32_t d = -234;  //0xffffff16

    char aStr[10]={0};
    char bStr[10]={0};
    char cStr[10]={0};
    char dStr[10]={0};

    // 修正a的格式符:使用%04hx或标准宏PRIx16
    snprintf(aStr, sizeof(aStr), "%04hx", a);
    // 等价于:snprintf(aStr, sizeof(aStr), "%04" PRIx16, a);

    snprintf(bStr, sizeof(bStr), "%04x", b & 0xFFFF);
    
    // 修正c的格式符:使用%08x或标准宏PRIx32
    snprintf(cStr, sizeof(cStr), "%08x", c);
    // 等价于:snprintf(cStr, sizeof(cStr), "%08" PRIx32, c);

    snprintf(dStr, sizeof(dStr), "%08x", d & 0xFFFFFFFF);

    fprintf(stdout, "TX a = %s.\n", aStr);
    fprintf(stdout, "TX b = %s.\n", bStr);
    fprintf(stdout, "TX c = %s.\n", cStr);
    fprintf(stdout, "TX d = %s.\n", dStr);

    /********************* B *******************/

    uint16_t aOut = 0;
    int16_t bOut = 0;
    uint32_t cOut = 0;
    int32_t dOut = 0;

    // 修正a的解析格式符:使用%hx或标准宏SCNx16
    sscanf(aStr, "%hx", &aOut);
    // 等价于:sscanf(aStr, "%" SCNx16, &aOut);

    sscanf(bStr, "%04x", &bOut);
    
    // 修正c的解析格式符:使用%x或标准宏SCNx32
    sscanf(cStr, "%x", &cOut);
    // 等价于:sscanf(cStr, "%" SCNx32, &cOut);

    sscanf(dStr, "%08x", &dOut);

    fprintf(stdout, "rx a = %" PRIu16 "\n", aOut);  // 使用PRIu16输出uint16_t
    fprintf(stdout, "rx b = %" PRId16 "\n", bOut);
    fprintf(stdout, "rx c = %" PRIu32 "\n", cOut);
    fprintf(stdout, "rx d = %" PRId32 "\n", dOut);

    return 0;
}

修复后,aOut会正确解析为43,同时代码的可移植性也得到提升。

内容的提问来源于stack exchange,提问作者yimejah505

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:31:34