函数顺序点分析和可变参数函数

函数分析

1. 说明
  1. 程序的内存布局

    1. 堆栈段在程序运行后才正式存在,是程序运行的基础
    2. .bss段存放的是未初始化的全局变量和静态变量
    3. .text段存放的是程序的可执行代码
    4. .data段保存的是已经初始化了的全局变量和静态变量
    5. .rodata段存放程序中的常量值,如字符串常量
    • 如图

内存映射

程序映射

  1. 函数的活动记录

    1. 临时变量域:存放临时变量的值,如k++的中间结果
    2. 局部变量域:用来存放函数本次执行中的局部变量
    3. 机器状态域:用来保存调用函数之前有关机器状态的信息,包各种寄存器的当前值和返回地址等
    4. 实参数域:存放函数的实参信息
    5. 返回值域:为调用者函数存放返回值
    • 如图:

活动记录

2.函数的顺序点
  1. 说明:

    1. 程序中存在顺序点,顺序点是执行过程中修改变量值最晚的时刻
    2. 在程序到达顺序点的时候,之前做的一切修改必须反映到后续的访问中
    3. 顺序点的判断

    1. 每个完整的表达式结束时
    2. &&||?:逗号表达式的每个运算对象计算之后
    3. 函数调用中对所有实际参数的求值完成之后(进入函数体之前)
  • 示例:

  • void f(int k, int j)
    {
        /*结果是i = 2, j = 1*/
        /*
        在执行函数前,先对实参i++进行计算的到2,把内存中指向实参i的内容改变为2,
        然后复制给形参k,由于i++是告诉系统我自己可以最后取值(目前是在临时变量域取值1),所以i的值还是1并且复制给j,
        在执行完后,i才真正的变成2
        */
        printf("k = %d, j = %d\n", i, j);
    }
    
    int main()
    {
        int k = 2;
        int a = 1;
    
        k = k++ + k++;  //顺序点是最后的分号
        printf("k = %d\n", k);  //k的值最后为6(考虑运算符优先级)
        /*先进行两个k++操作,但是没有到顺序点,所不能立即生效,
        然后执行中间的加法操作 k = 4 然后到达顺序点,然后进行两次++操作,然后赋值给最终的k*/
    
        if(a-- && a)  //a-- begin a = 0
        {
            printf("a = %d\n", a);
        }
    
        int i = 1;
        f(i, i++);  //顺序点是函数执行前,参数列表要计算完
        return 0;
    }
    3.可变参数
    1. 说明:

      1. 参数可变函数依赖于头文件stdarg.h
      2. 可变参数必须从头到尾按照顺序逐个访问
      3. 参数列表中至少存在一个确定的明名参数
      4. 可变参数宏无法判断实际存在的参数的数量
      5. 可变参数宏无法判断参数的实际类型
      6. va_list变量与va_start,va_end,和va_arg配合使用能够访问参数值

        1. va_arg中如果指定了错误的类型,那么结果是不可预测的
      7. 无法直接访问可变参数列表中间的参数值

    2. 示例:

    #include <stdarg.h>
    
    float average(int n, ...)
    {
        va_list args;  //使用可变参数列表声明变量
        int i = 0;
        float sum = 0;
    
        va_start(args, n);  //开始可变参数的读取
    
        for(i = 0; i < n; ++i)
        {
            sum += va_arg(args, int);  //按顺序读取可变参数
        }
    
        va_end(args);  //结束可变参数的读取
        return sum / n;
    }
    
    int main()
    {
        printf("%-.3f\n", average(5, 1, 2, 3, 4, 5));
        printf("%-.3f\n", average(4, 1, 2, 3, 4));
        return 0;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值