Поскольку я хочу отслеживать некоторые переменные, чтобы увидеть, как они меняются, я хочу создать функцию, которая получает строку формата в зависимости от типа переменной и указателя на значение.Я надеюсь, что с помощью строки формата printf правильно определит значение.На самом деле это работает, но с одним исключением - значения с плавающей точкой не печатаются должным образом.
Это мой код:
#include <stdio.h>
void pprint (char* fmtstr, void* p)
{
printf(fmtstr,*(long double *)p);
}
int main (int argc, char **argv)
{
char cval = 64;
int ival = -534;
unsigned int iuval = 535;
float fval = 534.64;
double dval = 53432.1;
long double ldval = 534321234.134567;
long long lval = -654321;
unsigned long long luval = 7654321;
pprint ("char: %hhd\n",&cval);
pprint ("int: %d\n",&ival);
pprint ("uint: %u\n",&iuval);
pprint ("float: %f\n",&fval);
pprint ("double: %f\n",&dval);
pprint ("long double: %Lf\n",&ldval);
pprint ("llong: %lld\n",&lval);
pprint ("ullong: %llu\n",&luval);
return 0;
}
И результаты:
char: 64
int: -534
uint: 535
float: 0.000000
double: 53432.100000
long double: 534321234.134567
llong: -654321
ullong: 7654321
Как мы видим, все напечатано нормально, кроме поплавка.Однако после некоторой модификации функции pprint (приведение пустого указателя к плавающей точке):
printf(fmtstr,*(float*)p);
Результаты будут такими:
char: 0
int: 1073741824
uint: 0
float: 534.640015
double: 0.000000
long double: 0.000000
llong: -351285912010752
ullong: 4038940431088615424
Теперь только значение с плавающей точкой печатается правильно.Другим побочным эффектом является то, что приведение к любому другому типу приводит к успешной печати типов с меньшим или одинаковым размером.(Если я приведу к int, он будет правильно печатать символы, но не длинные).Таким образом, приведение к long double решает эту проблему, поскольку он имеет наибольший размер.
Однако проблема с плавающей точкой остается.Чтобы напечатать значение с плавающей точкой, мне нужно привести указатель к плавающей точке, но не более того.И наоборот: когда я бросаю на плаву, все, кроме плавания, не получается.Разве разыменование не связано со считыванием данных, расположенных по указанному адресу, и передачей их в printf?(тот же указатель, приведенный к любому типу, содержит тот же адрес?) Затем строка формата может «читать» данные байты в правильном формате - char, int, unsigned int и т. д.
Iслышал, что значения с плавающей запятой в функциях с переменными числами преобразуются в двойные.Это связано с проблемой?Кроме того, в некоторых случаях я не могу предоставить значение как double - потому что, например, многие из переменных, используемых в Opengl, являются числами с плавающей запятой (GLfloat).
В итоге у меня есть 2 вопроса.
Почему поплавки ведут себя не так, как все остальные типы.
Может ли использование этой функции привести к побочным эффектам?Я имею в виду, что при печати, например, int, printf получает 12 байтов (sizeof (long double)) в качестве второго параметра, но читает только 4 (строка формата "% d").Из этих 12 байтов первые 4 принадлежат значению int, которое я хочу напечатать, а следующие 8 являются ненужными, которые никогда не читаются printf.Это проблема?
Спасибо.