查看: 1790|回复: 0

一道涉及C语言形参面试题的剖析 by 戴上举

[复制链接]
  • TA的每日心情
    郁闷
    2024-10-28 10:11
  • 签到天数: 1703 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    发表于 2013-8-16 17:02:08 | 显示全部楼层 |阅读模式
    分享到:
    发现对C语言函数形参进行说明的文章点击率远高于其它文章,看来大家对C语言的热情可不是一般,难怪谭浩强教授那本C语言的书发行量能过千万册,显然是有坚实的群众基础。既然大家都偏好C语言的相关知识,今天我们来剖析一道C语言的面试题,这道题除了考察对C语言函数形参的理解外,还有对++这类操作先加还是后加掌握程度的考察。

    题目见下,可以直接用VC进行编译运行,另外这道题也不是我出的,只是借来一用,不代表我完全认同其代码规范格式。

    #include

    typedef struct{int b,p;}S;

    void f(S s)

    {
    int a="1",b=2,c=3,d=4,m=2,n=2;
    (m=a>b)&&(n=c>d);
    printf("m=%d,n=%d\n",n,m);
    s.b+=1;
    s.p+=2;
    }

    void fun(char *a,char *b)
    {
    a="b";
    (*a)++;
    }
    void main(void)
    {
    int i;
    unsigned int array[32],*p;
    char c1='A',c2='a',*p1,*p2;
    S s={1,2};

    f(s);
    printf("%d,%d\n",s.b,s.p);
    p1=&c1;
    p2=&c2;
    fun(p1,p2);
    printf("%c%c\n",c1,c2);

    i="7"&3+12;
    p="array";
    *(p++)=++i;
    printf("%d\n",array[0]);
    *(p)=i++;
    *(p++)+=++i;
    printf("%d\n",array[1]);

    }

    运行结果分析:
    void main(void)
    {
    int i;
    unsigned int array[32],*p;
    char c1='A',c2='a',*p1,*p2;
    S s={1,2};
    完成main()函数中的变量初始化
    没有特别需要注意的地方
    假定结构s分配到的地址为s_main

    f(s);
    进入函数fun(),main()函数中结构s的起始地址 s_main会传给函数fun()
    进入函数fun()会先另外分配一段空间s_f,并把s_main的值传给s_f
    void f(S s)
    int a="1",b=2,c=3,d=4,m=2,n=2;
    完成fun()函数中变量的初始化
    (m=a>b)&&(n=c>d);
    这里考察对运算符以及运算优先级别的理解
    1.考察队=和><运算符优先级的掌握程度,><运算符优先级比=高
    所以(m=a>b)实际上为(m=(a>b)),先执行a>b操作,此时a=1,b=2,执行结果不为真,也就是m=0,m的值从2变为0
    (n=c>d)同理,如果执行完(n=c>d)应该是n的值从2变为0
    2.考察对&&运算符的理解,因为是条件与,如果前一个条件不为真,就不会进行后面的处理
    因为(m=a>b)得结果是m=0,所以&&不用再进行其右边的运算,(n=c>d)没有执行,n的值保持不变
    printf("m=%d,n=%d\n",n,m);
    到这里m的值为0,n为2,正常输出即可
    留意这里会额外考察面试者看题的细致程度,输出格式交换了m和n,最终输出应为“m=2,n=0”
    s.b+=1;
    s.p+=2;
    这里的s实际上是s_f.b加1和s_f.p加2,s_main.b和s_main.p的值均保持不变
    这就是之前我分析的形参的处理方法,可以将其当成函数的局部函数,调用时从别处取到初始值

    printf("%d,%d\n",s.b,s.p);
    这里考察的是对函数形参的理解
    到这里函数f()已经执行完返回到main()函数中,函数f()中使用的s_f已经释放掉
    所以输出实际还是没有改变的s_main.b和s_main.p,最终输出为“1,2”
    p1=&c1;
    p2=&c2;
    fun(p1,p2);
    这里也是考察队函数形参的理解,不过这里的参数是指针,所以结果会和前面的f()有所不同
    void fun(char *a,char *b)
    进入函数时候fun()也会分配两个指针a_fun和b_fun
    调用函数fun()会先将p1_main和p2_main的值传递给a_fun和b_fun
    a="b";
    这一句执行结果是a_fun从p1_main变为b_fun,也就是p2_main
    (*a)++;
    指针操作,此时a_fun等于p2_main,指向main()中c2所在的地址,实际结果为将c2所在的地址的内容加1
    printf("%c%c\n",c1,c2);
    因为前面将c2所在的地址的内容加了1,实际上就是c2内容已经被加了1,最终输出应为“A,b”
    对比函数f(),作为形参的p1和p2内容同样没有改变,但是函数fun()中改变了指针所指向地址的内容,从而改变了main()函数中的相应内容

    i="7"&3+12;
    考察的是对运算符的掌握程度,实际等效为i=7&(3+12)=7
    p="array";
    取数组的首地址给指针p
    *(p++)=++i;
    考察对i++和++i这类操作的理解,p先用再加,i先加再用,实际等效为下面
    i="i"+1;这里i变为8
    (*p)=i;这里p指向array[0]的地址,所以array[0]变为8
    p="p"++;这里p改指向array[1]的地址
    printf("%d\n",array[0]);
    最终输出应为“8”
    *(p)=i++;
    i先用再加,实际等效为下面
    (*p)=i;此时i依然为8,p指向array[1],所以array[1]变为8
    i="i"+1;i的内容变为9
    *(p++)+=++i;
    p先用再加,i先加再用,实际等效为下面
    i="i"+1;i的内容变为10
    (*p)=(*p)+i;此时p指向array[1],i为10,array[1]为8,执行结果是array[1]变为18
    p="p"+1;
    printf("%d\n",array[1]);
    最终输出应为“18”
    }
    (全文完)

    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-25 12:49 , Processed in 0.111040 second(s), 15 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.