C语言很有意思的问题,参数中引用多个函数,这些函数从哪个开始计算?

113 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情

简介

先说结论,从后向前,嵌套时也是先处理第一层,再处理第二层,每层都是从后向前

  • 验证一个很有意思的现象,下面的这个函数,从传参0开始使用find函数,还是从4开始?
#include <stdio.h>
#include <stdlib.h>

static char* string[] = {
    "0",
    "1",
    "2",
    "3",
    "4",
    NULL
};

static inline char* find(int index)
{
    if (index < (sizeof(string) / sizeof(char*) - 1))
        return string[index];
    else
        return "unknow";
}

int main(int args, char* argc)
{
    printf("%s %s %s %s %s\n",\
        find(0),\
        find(1),\
        find(2),\
        find(3),\
        find(4));

    return 0;
}
  • 为什么会引发这个问题???

有时候,会出现这种引用多个函数的问题,而且这个函数从前往后和往后往前在性能上优化空间,如果能确定顺序,那么是很棒棒哒,but~~~,竟然发现这个顺序还真的和大家以为的平常的从前向后不一样。。。

验证

  • 给函数里面加一行打印
    static inline char* find(int index)
    {
        printf("from %d\n", index);
        
        if (index < (sizeof(string) / sizeof(char*) - 1))
            return string[index];
        else
            return "unknow";
    }
    
  • 试一下
    [kira@localhost test]$ gcc main.c
    [kira@localhost test]$ ./a.out 
    from 4
    from 3
    from 2
    from 1
    from 0
    0 1 2 3 4
    [kira@localhost test]$ 
    

what!!! 竟然是从后往前!!!

  • 再添加别的函数也一样
    static char* look(void)
    {
        printf("this is function look\n");
    
        return "look what?";
    }
    
    int main(int args, char* argc)
    {
        printf("%s %s %s %s %s %s\n",\
            find(0),\
            find(1),\
            find(2),\
            look(),\
            find(3),\
            find(4));
    
        return 0;
    }
    
  • 执行结果
    [kira@localhost test]$ ./a.out 
    from 4
    from 3
    this is function look
    from 2
    from 1
    from 0
    0 1 2 look what? 3 4
    

嵌套起来试一下

  • 再添加一个函数
    static char* strandstr(char* s1, char* s2)
    {
        static char mess[20];
    
        printf("function %s and %s \n", s1, s2);
    
        sprintf(mess, "%s and %s", s1, s2);
    
        return mess;
    }
    
    int main(int args, char* argc)
    {
        printf("%s %s %s %s %s %s %s\n",\
            find(0),\
            find(1),\
            find(2),\
            look(),\
            strandstr(find(0), find(1)),\
            find(3),\
            find(4));
    
        return 0;
    }
    
  • 执行结果
    [kira@localhost test]$ ./a.out 
    from 4
    from 3
    from 1
    from 0
    function 0 and 1 
    this is function look
    from 2
    from 1
    from 0
    0 1 2 look what? 0 and 1 3 4
    [kira@localhost test]$ 
    

规律

  • 首先,遇到传参是函数,需要先计算函数内容的,会从后往前计算,这一点挺反直觉的,很有意思
  • 如果传参是函数,函数又依赖函数作为传参,那么会依然先处理这个函数内的后一项,从后往前进行计算

性能问题

例如,环形数组,如果按顺序取出时候,毫无疑问正序时候最快彩超到下一个结果,如果再这时候反序必然会导致需要遍历整个数组,这时候可能需要使用者避免使用这种自动化的隐式传参了,最好是先计算出来,再把结果传参,这样最多会写出来不美观,对性能的影响可以忽略不计。

完结、撒花