addi писал(а): ↑15 май 2022, 20:26
Здравствуйте!
Подскажите пожалуйста что может быть не так с использованием sscanf, sprintf, stdio.h
Попробовал использовать эти функции без включения stdio.h, все успешно компилировалось но с предупреждением что функции используется без прототипа
На практике они у меня не заработали
Если же включать в код stdio.h то возникает ошибка - "конфликт типов"
Также пробовал форматировать также через sprintf и также вместо u X формат, все бузуспешно
Прошу помочь разобраться
Доброго времени суток!
1) Для правильной передачи параметров функции компилятор должен знать какую функцию мы вызываем, для этого и используется прототип функции. Прототипы функций для работы с вводом/выводом информации описаны в файле stdio.h. Также можно указать прототип только одной функции, например:
Код: Выделить всё
extern int sprintf (char *,const char *, ...);
Если собрать проект без прототипа функции, то компилятор часть параметров передаст не через стек, а через рабочие регистры, что не будет соответствовать ожидаемым параметрам в теле функции. А в прототипе функции как раз и указано, каким образом передавать параметры при вызове функции.
При несоответствии передаваемых параметров функции и получим неработающий код.
Дисассемблер вызова функции без объявления прототипа
; sprintf((char*)data2, "%1u%2u%1u%2u",(unsigned char)&pref, (unsigned char)&aa, (unsigned char)&bb, (unsigned char)&dd );
388B*C91502 PUSH #0215
388E C90902 PUSH #0209
3891 A30106021C LD AX,data2[00]
3896 A1D1381E LD BX,#38D1
389A A1170220 LD CX,#0217
389E A1080222 LD DX,#0208
38A2 EF1EF1 LCALL sprintf
Дисассемблер вызова функции с объявлением прототипа через #include <stdio.h>
; sprintf((char*)data2, "%1u%2u%1u%2u",(unsigned char)&pref, (unsigned char)&aa, (unsigned char)&bb, (unsigned char)&dd );
388D*C91502 PUSH #0215
3890 C90902 PUSH #0209
3893 C90802 PUSH #0208
3896 C91702 PUSH #0217
3899 C9D138 PUSH #38D1
389C A30106021C LD AX,data2[00]
38A1 EF1FF1 LCALL sprintf
2) Первым параметром функции sprintf(), sscanf() должен быть указатель на массив символов, в который функция sprintf() записывает форматированную строку, а функция sscanf() считывает. Поэтому, если массив символов объявлен как массив
char data[10];, то вызов функций будет следующим:
Код: Выделить всё
char data[10];
volatile unsigned char aa,bb,cc;
void main()
{
sscanf(data, "%1u%2u%1u",&aa, &bb, &dd );
sprintf(data, "%X\n",aa);
}
Если же массив символов объявлен через указатель, то при вызове функции мы должны привести тип данных к (char*), и вызов функций будет следующим:
Код: Выделить всё
volatile char* data;
volatile unsigned char aa,bb,cc;
void main()
{
data = (char*)malloc(8 * sizeof(char));
sscanf((char*)data, "%1u%2u%1u",&aa, &bb, &dd );
sprintf((char*)data, "%X\n",aa);
}