c文件中的函数原型范围,而不是标头

c文件中的函数原型范围,而不是标头,c,scope,C,Scope,如果以前有人问过这个问题,我表示歉意(我只发现这个问题的变体,但不是确切的变体) 我的问题是关于定义功能原型的范围w.r.t 假设我们有3个文件:test.h,test.c,main.c main.c和test.c都包括test.h 测试.c: int f2(int b); // function prototype (local) int x=0; // public function int f1(int a){ return a*5; } // local function

如果以前有人问过这个问题,我表示歉意(我只发现这个问题的变体,但不是确切的变体)

我的问题是关于定义功能原型的范围w.r.t

假设我们有3个文件:
test.h
test.c
main.c

main.c
test.c
都包括
test.h

测试.c

int f2(int b); // function prototype (local)

int x=0;
// public function
int f1(int a){
 return a*5;      
}
// local function
int f2(int b){
 return b*10;
}
int f1(int a);
#include "test.h"
int x=1;
int main(){
    printf("%d \n", f1(5));
    printf("%d \n", f2(5));
    return 0;
}
测试.h

int f2(int b); // function prototype (local)

int x=0;
// public function
int f1(int a){
 return a*5;      
}
// local function
int f2(int b){
 return b*10;
}
int f1(int a);
#include "test.h"
int x=1;
int main(){
    printf("%d \n", f1(5));
    printf("%d \n", f2(5));
    return 0;
}
main.c

int f2(int b); // function prototype (local)

int x=0;
// public function
int f1(int a){
 return a*5;      
}
// local function
int f2(int b){
 return b*10;
}
int f1(int a);
#include "test.h"
int x=1;
int main(){
    printf("%d \n", f1(5));
    printf("%d \n", f2(5));
    return 0;
}
我的问题是:

  • Can
    main.c
    access
    f2()
    test.c
  • 能否
    main.c
    访问
    f1()
    ?还是需要声明为
    extern
  • main.c
    是否可以访问
    test.c
    中的
    x
    全局变量?它是否与
    main.c
    中定义的全局变量
    x
    (同名)冲突
  • 要获得本地范围,是否必须使用
    静态
    关键字
  • 静态函数能否访问同一
    .c
    文件中定义的全局变量(静态/非静态)
  • 是的,但不小心。没有声明符的函数将默认为
    int
    type,其参数将默认为
    int
    type,存储类将默认为
    extern
    。您的函数恰好已经具有这些类型。因此,严格地说,不需要声明器(尽管不使用声明器是一种非常糟糕的做法)。然而,这在C99中显然是非法的,如果您使用的是C99语义,您应该会得到一个错误;否则它只是一个警告(
    -Wimplicit函数声明

    2) 如上所述,
    test.h
    声明符中缺少存储类说明符将隐式地将
    f1
    声明为extern。一切都很好

    3) 链接器将引发有关重复标识符的错误。如果使用
    extern int x(没有初始化),它可以工作。变量不会得到隐式声明;如果您只是尝试在
    main.c
    中使用
    x
    ,而不使用上述声明,您将得到一个关于使用未声明变量的错误

    4)
    static
    表示几种不同的含义。我假设这个问题是关于静态函数的。这仅限制函数对当前编译单元的可见性;没有其他影响

    5) 如上所述,将函数设为静态只会影响可以访问它的内容,而不会影响它可以访问的内容

    main.c能否访问在test2.c中实现并声明原型的f2()

    函数
    f2
    将作为默认函数,其返回值为int,参数
    int
    如有。但是,如果使用不同的参数,则会出现错误

    从C99开始,默认函数不适用,这将给出一个错误

    main.c能否访问f1()?还是需要声明为extern

    是的,它可以访问f1(),因为您已经包含了
    test.h
    ,但是您还需要编译
    test.c
    ,并将这两个文件都提供给链接器

    test.h
    中的
    f1()
    声明不需要声明为extern。默认情况下,函数声明是extern

    main.c是否有权访问test.c内部的x全局变量?它会与main.c中定义的全局变量x(同名)冲突吗

    您需要将变量链接在一起。一旦你这样做了,你会得到一个链接器错误

    要获得本地范围,是否必须使用static关键字

    如果变量在函数外部声明,则它是全局变量。要使其成为本地范围,您需要专门使用static关键字

    静态函数能否访问同一.c文件中定义的全局变量(静态/非静态)


    是的

    在回答您的问题时,我假设这两个.c源代码被编译并链接到一个程序中

    • Can
      main.c
      access
      f2()
      test2.c
    现代C不允许调用在作用域中没有声明的函数,但K&R C确实允许这样的调用,而且大多数实现仍然允许这样的调用。此外,
    main.c
    可以声明函数本身,然后调用它

    • 能否
      main.c
      访问
      f1()
      ?还是需要声明为
      extern
    默认情况下,函数具有外部链接。因此,
    extern
    是函数声明的默认值。您可以明确指定
    extern
    ,但这是多余的

    • main.c
      是否可以访问
      test.c
      中的
      x
      全局变量?它是否与中定义的全局变量
      x
      (同名)冲突 梅因c
    是和否。一个程序包含具有外部链接的同一标识符的两个定义是错误的,并且您的
    x
    声明确实构成了定义,并且它们确实(默认情况下)具有外部链接

    但是,有些实现会将这些变量合并到一个变量中,有些实现会拒绝链接程序,有些实现甚至可能会维护单独的
    x
    变量

    顺便说一句,声明跨源文件共享的变量的正确方法是每个文件声明它,
    extern
    ,但只有一个文件初始化它。通常,没有初始值设定项的
    extern
    声明将进入头文件,而带有初始值设定项的单个声明(使其成为一个定义)将进入一个.c文件。例如:


    测试.h

    extern int x; // _with_ extern, _without_ initializer
    

    test.c

    #include "test.h"
    int x = 0;  // 'extern' is optional here
    
    #include "test.h"
    // no further declaration of x here
    

    main.c

    #include "test.h"
    int x = 0;  // 'extern' is optional here
    
    #include "test.h"
    // no further declaration of x here
    

    • 到ga