由于我想跟踪一些变量以便查看它们如何变化,因此我想创建一个函数,该函数根据变量的类型和指向值的指针接收格式字符串。我希望,在格式字符串的帮助下, 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 函数进行一些修改之后(将 void 指针转换为 float):
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 等。
我听说,可变参数函数中的浮点值会转换为双精度值。这与问题有关吗?另外,在某些情况下,我无法提供双精度值 - 因为例如 Opengl 中使用的许多变量都是浮点数 (GLfloat)。
总而言之,我有2个问题。
为什么浮动的行为与所有其他类型不同。
使用这个功能会产生副作用吗?我的意思是,当打印例如 int 时, printf 接收 12 个字节 (sizeof(long double)) 作为第二个参数,但只读取 4 个字节(“%d”格式字符串)。在这 12 个字节中,前 4 个属于我要打印的 int 值,接下来的 8 个是垃圾,printf 永远不会读取它们。这是一个问题吗?
谢谢。