一个选择题,不明白,求解解决办法

一个选择题,不明白,求解
一个选择题,不明白,求解解决办法

------解决思路----------------------
楼主这个也想不明白吗?
FA调用FB,若FB出现在FA之后,FA调用FB时,不认识FB,所以报错,需要把FB的原型放到FA的前边
------解决思路----------------------
D也不对呀!
虽然从实践上D的说法是没错的,但是并不是必须

#include <stdio.h>

int
FA(void)
{
    int x, y;
    double FB(int x, int y);

    x = 1;
    y = 2;
    printf("%f\n", FB(x, y));

    return 0;
}

double
FB(int x, int y)
{
    return (x + y) / 2.0;
}

int
main(int argc, char *argv[])
{

    FA();
    return 0;
}

------解决思路----------------------
这是函数定义和函数声明区分
“函数定义可以以任意次序出现在一个源文件或多个源文件中,但同一函数不能分割存放在多个文件中。如果源程序分散在多个文件中,那么,在编译和加载时,就需要做更多的工作,但这是操作系统的原因,并不是语言的属性决定的。”-K&R
注:函数定义的自由先决条件是有函数声明在先

由于C是强类型语言,任何变量在使用之前都必须告知编译器它的类型,函数不例外!而且在使用时候要做类型检查!函数调用属于表达式的范畴,当归约识别出是函数调用时,就要从符号表中获取此函数的信息,以匹配和检查参数的传递,确保参数合法性从而保证函数的正确使用!——这些都是编译器的工作!

目前C编译器都是LL实现,从左到右,从先到后语法解析源程序,因此先出现的标识(变量名,函数名)先进入符号表,如果一个函数FB未定义又没有声明,那么它就不会出现在符号表当中,而此时若有函数FA调用FB,只会报错函数FB未定义,也就是调用非法,因为FB根本不存在符号表中,找不到它任何信息,报错!如果只声明FB而没有定义FB,然后FA调用FB,编译能通过,但链接就会出错喽!也就是符号表中已经有它的信息,函数调用语法归约和类型检测能够顺利进行,编译能通过,但是链接时就找不到FB的地址了,没有定义嘛!

ls上hacker给出了另外一种告知方式,它是正确可执行的。依据C文法,函数声明和变量声明最终都到declaration-list,无论是全局的还是局部的,只要是合法的声明,相关符号属性都会放入符号表!但是本质不一样,放在函数内,它是局部声明,在函数局部符号表内,而不是全局符号表。放在函数外,则是在全局符号表内。虽然表面效果一样,但是机理还是有区分的。提醒这一点吧,并无它意!
下面代码可以验证它的作用域


#include <stdio.h>


int FA(void)
{
int x, y;
double FB(int x, int y);

x = 1;
y = 2;
printf("%f\n", FB(x, y));

return 0;
}

int FC(void)
{
    int x, y;

    x = 1;
    y = 2;
    printf("%f\n", FB(x, y));//gcc编译报错,上面FB声明只在局部符号表内

    return 0;
}

double FB(int x, int y)
{
    return (x + y) / 2.0;
}

int main(int argc, char *argv[])
{
    FA();
    FC();
    return 0;
}



gcc编译信息

declaration.c:23:20: error: incompatible implicit declaration of function ‘FB’
     printf("%f\n", FB(x, y));
                    ^
declaration.c:8:9: note: previous implicit declaration of ‘FB’ was here
  double FB(int x, int y);
         ^
declaration.c:23:5: warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=]
     printf("%f\n", FB(x, y));
     ^



------解决思路----------------------
编译是有顺序的,所以 FA 跟FB  肯定有编译顺序,如果 FA 调用FB, 若FB在FA前定义,那么不用声明,直接调用即可,因为FB是在FA之前已经通过编译的。若 FB在FA之后,那么就需要先声明FB,不然FA调用FB的时候编译器不知道谁是FB……

所以如果FA调用FB的话 选D
反之,如果FB调用FA的话 选C