printf通过给定的指针和格式字符串。 问题与浮游物

由于我想跟踪一些变量以查看它们如何变化,我想创建一个函数,该函数接收格式字符串,具体取决于变量的类型和指向该值的指针。 我希望,在格式字符串的帮助下,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: %hhdn",&cval);
        pprint ("int: %dn",&ival);
        pprint ("uint: %un",&iuval);
        pprint ("float: %fn",&fval);
        pprint ("double: %fn",&dval);
        pprint ("long double: %Lfn",&ldval);
        pprint ("llong: %lldn",&lval);
        pprint ("ullong: %llun",&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

现在只有浮点值被正确打印。 另一个副作用是,转换为任何其他类型都会导致printf类型的大小较低或相同。 (如果我转换为int,它将打印正确的字符,但不会长)。 所以,长时间投射解决了这个问题,因为它是最大的尺寸。

但是,浮点问题仍然存在。 为了打印浮点值,我需要将指针转换为浮点,但没有别的。 而相反:当我投入浮动时,除浮动之外的所有东西都失败。 是不是与读取数据相关的取消引用,位于指向的地址并将其传递给printf? (相同的指针,转换为任何类型都保存相同的地址?)然后,格式字符串能够以适当的格式“读取”给定的字节 - char,int,unsigned int等。

我听说过,可变参数函数中的浮点值被转换为双精度值。 这是否与问题有关? 此外,在某些情况下,我无法提供双值 - 因为例如Opengl中使用的许多变量都是浮点数(GLfloat)。

总之,我有两个问题。

  • 为什么浮动行为与其他类型不同?

  • 这个功能的使用会导致副作用吗? 我的意思是,当打印一个int时,printf会接收12个字节(sizeof(long double))作为第二个参数,但只读4(“%d”格式的字符串)。 从这12个字节开始,前4个属于int值,我要打印,接下来的8个是垃圾,这些垃圾都不会被printf读取。 这是一个问题吗?

  • 谢谢。


  • 浮动行为有所不同,因为格式特定于期望32位大小的类型,并且您将它发送为64位大小的类型。 对于其他类型,你有幸获得排序。

  • 列出错误地使用库函数的副作用是没有意义的。

  • 修复代码。 我会查看vprintf()vsprintf()函数,或者更好的说明您的设计目的,可能会有比您展示的代码更简单,更可行的解决方案。


    这不会回答你的任何问题,但是如果你想要打印printf,你可能想看看vprintf。


    你很幸运(或不幸)印刷了你对这么多类型的期望。

    C标准在§7.19.6.1/ 9中说

    如果任何参数不是相应转换规范的正确类型,则行为是未定义的。

    特别是,许多实现使用不同的CPU寄存器将浮点数和整数传递给printf(),即使在源代码中写入了整数,“%f”也会使printf()访问浮点寄存器,反之亦然。

    作为例子,在我的系统上,你的程序的输出是

    char: -1
    int: 164124920
    uint: 164124916
    float: 0.000000
    double: 0.000000
    long double: 534321234.134567
    llong: 140733357512904
    ullong: 140733357512896
    

    char: -17
    int: 1200847080
    uint: 1200847076
    float: 534.640015
    double: 0.000000
    long double: 0.000000
    llong: 140734394235064
    ullong: 140734394235056
    
    链接地址: http://www.djcxy.com/p/90295.html

    上一篇: printf by given pointer and format string. Issue with floats

    下一篇: Navigation Drawer (Google+ vs. YouTube)