【发布时间】:2011-11-13 06:00:40
【问题描述】:
由于我想跟踪一些变量以查看它们如何变化,因此我想创建一个函数,该函数接收格式字符串,具体取决于变量的类型和指向值的指针。我希望,在格式字符串的帮助下, 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 指针转换为浮点数)之后:
printf(fmtstr,*(float*)p);
结果是:
char: 0
int: 1073741824
uint: 0
float: 534.640015
double: 0.000000
long double: 0.000000
llong: -351285912010752
ullong: 4038940431088615424
现在只有浮点值被正确打印。 另一个副作用是,转换为任何其他类型会导致成功 printf 的类型具有较小或相同的大小。 (如果我转换为 int,它将正确打印字符,但不会打印长字符)。因此,转换为 long double 解决了这个问题,因为它的尺寸最大。
但是,浮动的问题仍然存在。为了打印浮点值,我需要将指针转换为浮点,但仅此而已。反之亦然:当我投射到浮动时,除了浮动之外的一切都失败了。解引用不是与读取数据相关,位于指向的地址并将其传递给 printf 吗? (相同的指针,转换为任何类型都拥有相同的地址?)然后,格式字符串能够以正确的格式“读取”给定的字节 - char、int、unsigned int 等。
我听说,可变参数函数中的浮点值被转换为双精度值。这与问题有关吗?此外,在某些情况下,我无法将值提供为双精度值 - 因为例如 Opengl 中使用的许多变量都是浮点数 (GLfloat)。
总的来说,我有 2 个问题。
为什么浮点数的行为不同于所有其他类型。
使用此功能会产生副作用吗?我的意思是,当打印例如一个 int 时,printf 接收 12 个字节(sizeof(long double))作为第二个参数,但只读取 4 个(“%d”格式字符串)。从这 12 个字节中,前 4 个属于我要打印的 int 值,接下来的 8 个是垃圾,printf 永远不会读取它们。这是个问题吗?
谢谢。
【问题讨论】:
-
tl;dr,但请注意,当通过可变参数传递时,浮点数会提升为双精度数。注意只有一个
%f格式说明符,没有什么“更短”的了。另外,你的文字是错误的。
标签: c pointers floating-point printf