首页 > 编程语言 > 详细

C++ printf 可变长参数输出的实现

时间:2020-06-16 22:59:20      阅读:79      评论:0      收藏:0      [点我收藏+]

今天看到一个问题,我们怎么确定printf中的可变参数。

 

这样,我们先从汇编的角度去理解一个东西,栈

char *p = (char*)malloc(256 << 20) + (256 << 20);
__asm__ volatile("movl %0, %%rsp\n", "r"(p));

这段代码的意思很简单,我们分配了256MB字节长度的空间,让sp寄存器指向这段空间的末尾

每次推元素入栈,都会执行指令inc sp,然后把数据放入ss:sp

所以栈中的空间一定是先入栈的地址高,后入栈的地址低

 

好的,理解了这个,再来看这段代码

void f(int a, int b, int c, int d){
    printf("%d", &a);
    printf("%d", &b);
    printf("%d", &c);
    printf("%d", &d);     
}

运行之后,发现a的地址最低,d的地址最高,每个参数间只差了一个sizeof int的大小

这说明d先入栈,然后c,b,a,入栈的地址是连续的,我们理解了这个,就能解开printf的面纱了

 

void f(const char * fmt, ...) 
{
    char* p;
    p = ((char*)&fmt) + sizeof(fmt);
    printf("%d\n", *(int*)p);  
        
    p =  p + sizeof(int);
    printf("%d\n", *(int*)p);

    p =  p + sizeof(int);
    printf("%s\n", *((char**)p));
}

int main()
{
    f("%d %d %s\n", 4, 5, "hello world");
   return 0;
}

在f中,标准字符串fmt的地址在最低处,然后我们用它的地址加上它本身的地址,就是第一个参数的地址

通过读取fmt的内容确定其类型(虽然我直接写的hhh

然后用该类型指针输出这个地址的内容,直到读到fmt的末尾

 

这个函数的实现,说明了C/C++在编程上对地址操作巨大的自由性,比较神奇。

C++ printf 可变长参数输出的实现

原文:https://www.cnblogs.com/Hebut-Amadeus/p/13149483.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!