码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2020-06-16 23:15:06      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:汇编   ola   就是   数据   class   理解   字符串   可变参数   第一个   

今天看到一个问题,我们怎么确定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 可变长参数输出的实现

标签:汇编   ola   就是   数据   class   理解   字符串   可变参数   第一个   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!