• 走出自己的Windows开发,融入程序猿的开发


    自从2014.7.9加入**软研以来,一直都做windows UI方面的开发,主要语言为C++;时间很快就过去了,一直都没时间也许是没精力写一些记录,但越觉得写写文档的必要性了;那么果断的申请了博客,记录下以前的,今后的程序生涯的点点滴滴,一是鼓励自己不断沉淀技术,职业文化等等;再者以后也有一个可以属于自己的书房可以翻阅,回忆。时间已经很晚了,眼睛有些朦胧;

      刚看了看《系统程序猿的成长计划》,里面讲道了可变参数的简单机制剖析;大致就是一个压栈的匹配;

    printf想必大家都会熟悉的使用;她就是典型的可变参数列表。。。。

    int __cdecl printf (const char *format, ...);

    可变参数,大约是这么模板化的,

    1)他必须是在至少一个给定的参数后面出现;即 不能达到这样的牛叉的 printf(...);

    2)前列参数后,逗号隔开,续"..."三个点,达到C语言的语法要求

    这样的函数,即可叫可变参数函数;

    void fun()
    {
      int i = 100, j = 200, k = 300, l = 400;
      printf("%d, %d, %d", i, j, k, l);
    }

    系统会在栈区依次为l, k, j, i开辟空间;变量的申明是右向左依次展开的;

    在我的win8 64位系统开辟的内存,依次为 

    + &i  0x0018fe4c  int *
    + &j  0x0018fe40  int *
    + &k 0x0018fe34  int *
    + &l  0x0018fe28  int *

    他们是一个压栈的过程,栈的地址是向低地址延申的,但没搞明白为社么每次的间隔是12?!!也请朋友八卦一下;

    l,k,j,i依次压栈;我觉得三个%d,或许也会压栈另一个栈;

    栈 A                                  栈B

    + &i  0x0018fe4c  int *       %d
    + &j  0x0018fe40  int *      %d
    + &k 0x0018fe34  int *       %d
    + &l  0x0018fe28  int *

    两个栈依次取值,去第一个%d,去&i;---》去第2个%d,去&j;---》去第3个%d,去&k;---》....所以k没办法打印了

    打出结果确实是:

    100, 200, 300

    当然printf可能是这样的压栈对比出栈;自己写可变参数的函数时,可以借助参数的个数,即第一个参数把可变的参数个数穿进去;这样会以指针进行后续的查找;

    其实很简单,比如add(int num, ...)

    add(1, 100);

    add(2, 20, 30);

    add(4, 1, 2, 3, 5);

    指针直接定位到第一个参数;即参数1的地址,加法运算;指针偏移下个参数的字节,再接着加。。。。直到最后一个参数加完。

    这就证明了,很多东西是很有意思的,我们真的不能老四抱怨什么都不会,什么都不懂,没关系,一天记录一点儿,一天心情会变化一些。加油小权子!睡觉!!!那个地址偏移12,大家可以八卦一下!

  • 相关阅读:
    Class.forName和ClassLoader.loadClass的区别
    数据库连接池优化配置(druid,dbcp,c3p0)
    MySQL在默认事务下各SQL语句使用的锁分析
    ArrayList vs LinkedList 空间占用
    MySQL锁详解
    利用ConcurrentHashMap来实现一个ConcurrentHashSet
    list与Set、Map区别及适用场景
    实现一个原子的正整数类:AtomicPositiveInteger
    mysql如何处理亿级数据,第一个阶段——优化SQL语句
    java性能优化
  • 原文地址:https://www.cnblogs.com/zhyq/p/4565000.html
Copyright © 2020-2023  润新知