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)


Предполагам, че вашето внедряване използва подписани знаци. Форматът "%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