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

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

 

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

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

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

每次推元素入栈,都会执行指令dec 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++在编程上对地址操作巨大的自由性,比较神奇。

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

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

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

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/355623

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午10:26
下一篇 2023年3月2日 上午10:26

相关推荐