s(n)printf печатает больше символов, чем указано в спецификаторе формата

Я столкнулся с любопытной проблемой с sprintf во встроенной системе (Libelium Waspmote, похожей на Arduino), где sprintf выводит больше символов, чем указано в спецификаторе формата. В данном конкретном случае я использую %02X для вывода шестнадцатеричного значения байтов в массиве. Однако в некоторых байтах вместо 2 символов записывается 4 с префиксом FF перед фактическим значением байта. snprintf ведет себя аналогично, за исключением того, что он учитывает указанный размер буфера и просто печатает префикс.

Для справки, вот фрагмент кода, печатающий содержимое массива:

char *pduChars = (char *) malloc(17*sizeof(char));
pduData.toChar(pduChars);
for (int i = 0; i < 17; i++) {
    char asciiCharsS[5];
    char asciiCharsSN[3];
    int printedS = sprintf(asciiCharsS, "%02X", pduChars[i]);
    int printedSN = snprintf(asciiCharsSN, 3, "%02X", pduChars[i]);
    USB.print(printedS);
    USB.print(" ");
    USB.print(printedSN);
    USB.print(" ");
    USB.print(asciiCharsS);
    USB.print(" ");
    USB.print(asciiCharsSN);
    USB.println(" ");
}

И вывод из этого фрагмента (сокращенный только до ошибочных байтов): фактическая последовательность байтов должна быть 0x00 0xFC 0xFF 0xFF 0x48 0xA5 0x33 0x51

sprintf snprintf sprintf Buffer snprintf Buffer


2 2 00 00
4 4 FFFC FF
4 4 FFFF FF
4 4 FFFF FF
2 2 48 48
4 4 FFA5 FF
2 2 33 33
2 2 51 51

Я что-то упускаю из виду или это может быть проблема, связанная с платформой, связанная с реализацией s(n)printf?


person Seán Labastille    schedule 04.03.2013    source источник
comment
Может быть, на вашей платформе char составляет 2 байта? Обратите внимание, что 2 в %02X — это минимальная, а не максимальная длина.   -  person Shahbaz    schedule 04.03.2013
comment
sizeof(char) возвращает 1, поэтому кажется, что это не так.   -  person Seán Labastille    schedule 04.03.2013
comment
sizeof(char) всегда один. Это определяется стандартом. Но это не значит, что это один байт. На самом деле sizeof не дает количество байтов, он показывает размер относительно размера char.   -  person Shahbaz    schedule 04.03.2013
comment
Не забудьте free() памяти, выделенной для pduChars!   -  person pmg    schedule 04.03.2013


Ответы (3)


Я предполагаю, что ваша реализация использует символы signed. Формат "%X" предполагает значения без знака. Вместо этого используйте или используйте unsigned char.

/* cast */
int printedS = sprintf(asciiCharsS, "%02X", (unsigned char)pduChars[i]);
int printedSN = snprintf(asciiCharsSN, 3, "%02X", (unsigned char)pduChars[i]);

or

/* use unsigned char */
unsigned char *pduChars = malloc(17); /* cast is, at best, redundant */
                                      /* sizeof (char) is, by definition, 1 */
person pmg    schedule 04.03.2013

Модификаторы спецификатора формата, которые вы используете, используются только для заполнения. В случае, если количество символов значения превышает указанное значение, будет напечатана вся строка.

person Ivaylo Strandjev    schedule 04.03.2013

%02X предназначен для заполнения... он не будет пропущен... поэтому, если ваше значение больше указанного значения, будет напечатана вся строка

person Kinjal Patel    schedule 04.03.2013