`sprintf` %04d и %03x одновременно на Arduino

У меня есть этот код , работает отлично!

uint32_t id , id2;
char s[64];  // Должно быть достаточно

...   
id2 = id = CAN.getCanId();
sprintf (s, "%04d  : ", id );  // !!! ЗДЕСЬ !!!
Serial.print(s);

выход работает ОТЛИЧНО:

0031 : ...
2047 : ...
0031 : ...
2047 : ...
...

измените на эту строку:

sprintf (s, "(0x%03x) : ", id2 );

ТОЖЕ ОТЛИЧНО работает:

(0x01f) : ...
(0x7ff) : ...
(0x01f) : ...
(0x7ff) : ...

но, ЕСЛИ БЫ Я НАПИСАЛ это:

sprintf (s, "%04d(0x%03x) : ", id , id2 );  

выход:

0031(0x000) : ...
2047(0x000) : ...
0031(0x000) : ...
2047(0x000) : ...

ПОЧЕМУ? Почему %03x исчезает??

ПРИМЕЧАНИЕ
Я включил это:

#include <stdio.h>
#include <print.h>
#include <string.h>
#include <SoftwareSerial.h>
#include <Arduino.h>  // HC-05 BT
#include "DFRobot_MCP2515.h"

Я знаю, что могу написать вот так, чтобы решить:

            sprintf (s, "%04d", id );
            Serial.print(s);
            sprintf (s, "(0x%03x) : ", id2 );
            Serial.print(s);

Я не новичок в C,
Это просто заставляет меня чувствовать себя... странно...

, 👍0

Обсуждение

Почему вы используете uint32_t вместо int? Планируете ли вы использовать большие значения? Работают ли ваши тесты со значениями больше 16 бит?, @Juraj

@Juraj Спасибо, ты понял!! Код sprintf (s, "%04ld(0x%03lx) : ", id, id ); теперь работает отлично! id2 больше не нужен. :D, @James


1 ответ


2

Юрай дал вам хорошую подсказку по решению. Если вы включите компилятор, предупреждения, компилятор также сообщит вам, что не так:

warning: format ‘%d’ expects argument of type ‘int’, but argument 3
has type ‘uint32_t {aka long unsigned int}’ [-Wformat=]
     sprintf(s, "%04d(0x%03x) : ", id, id2);
                                          ^
warning: format ‘%x’ expects argument of type ‘unsigned int’, but
argument 4 has type ‘uint32_t {aka long unsigned int}’ [-Wformat=]

Вы предоставляете sprintf() два 4-байтовых целых числа. Вы также сообщаете (через строку форматирования) для чтения двух двухбайтовых целых чисел. Результат: что он считывает 4 байта (первое целое число) и интерпретирует их как два числа. Например, число 31 (0x0000001f) интерпретируется как 0x001f (т.е. 31) и 0x0000, в порядке младшего значащего бита.

Решения: Либо вы используете простые переменные int, либо указываете sprintf() что вы вместо этого передаете ему длинные целые числа, используя l префикс к формату: "%04ld(0x%03lx) : "

,

Да! После изменения кода на sprintf (s, "%04ld(0x%03lx) : ", id, id ); всё работает отлично! Большое спасибо., @James