sscanf 忽略两个连续字符串中的第一个。我需要适当的格式字符串

sscanf ignores the first of two consecutive strings. I need the appropriate format string

输出的第一行是提供给如下所示的 sscanf 命令的输入字符串

其他行只是扫描值的打印值,arg1 和 arg2 分别是 args uint16_t 参数的高字节和低字节。

我不明白为什么没有扫描 id01 并将其分配给 packet.identifier。

我需要一个可以同时获取 id01 和 switch 的工作格式字符串。 另外,非常感谢对格式字符串的解释。

提前感谢您的帮助:)

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

struct data_packet{
   char identifier[8];
   char command[8];
   uint8_t arg1;
   uint8_t arg2;
};

#define INPUT_STR "<<< id01 switch 0xAB29 >>>"
struct data_packet parse_input(char *input){
    //uint8_t exit_code = 1;
    struct data_packet packet;
    uint8_t conversions = 0;
    uint16_t args = 0;
    conversions = sscanf(input , "<<< %s %s %x >>>", packet.identifier, packet.command, &args);
    packet.arg1 = (args >> 8); // High Byte of args
    packet.arg2 = (args & 0x00FF); //Low byte of args
    //if (conversions == 3) exit_code = 0;
    //return exit_code;
    return packet;
}

int main(void){
    
    struct data_packet data = parse_input(INPUT_STR);
    printf("%s\n", INPUT_STR);
    printf("identifier: %s\ncommand: %s\narg1: 0x%0x\narg2: 0x%0x\n", data.identifier, data.command, data.arg1, data.arg2);


return 0;
}

运行 代码通过 online compiler 我看到了警告:

main.c:17:46: warning: format ‘%x’ expects argument of type ‘unsigned int *’,
but argument 5 has type ‘uint16_t * {aka short unsigned int *}’ [-Wformat=]
 conversions = sscanf(input , "<<< %s %s %x >>>", packet.identifier, packet.command, &args);
                                          ^

将声明更改为:

uint32_t args = 0;

它运行得很干净。

格式代码 %x 适用于 unsigned int,而非 uint16_t。格式说明符和参数类型不匹配导致 未定义的行为

对于 uint16_t 使用来自 <inttypes.h> header:

的 pre-defined 宏 SCNx16
sscanf(input , "<<< %s %s %" SCNx16 " >>>", packet.identifier, packet.command, &args);

可能发生的情况是,因为 unsigned int 通常是 32 位,所以 sscanf 函数会将这 32 位的一半写入您的其他变量之一。很可能 packet.identifier[0],它设置为零,恰好与字符串终止符相同。

如果您使用调试器查看 package.identifier 的实际内容,您可能会很快看到它。

并将此作为教训,始终 构建时启用额外的警告,并将它们视为 必须 修复的错误。