在头文件中定义一个变量,只有在没有 present extern 关键字的情况下才有效?

11 浏览
0 Comments

在头文件中定义一个变量,只有在没有 present extern 关键字的情况下才有效?

我目前正在学习C语言,但我真的不理解头文件是如何工作的,为了确保我有两个问题。

1)让我们来看一下下面的程序:main.c:

#include 
#include 
#include "functions.h"
int main( void )
{
    printf( "Num = %d\n", number );
    printNumber();
    return 0;
}

functions.c:

#include 
#include 
#include 
#include "functions.h"
void printNumber( void )
{
    printf("Number = %d\n", number );
}

functions.h:

#ifndef FUNCTIONS
#define FUNCTIONS
int number;
extern void printNumber( void );
#endif // FUNCTIONS

在头文件中,没有使用extern关键字,所以似乎没有引用到number,程序输出:

Num = 0
Number = 0

第一个问题是,number是否被初始化(如果number只在头文件中出现,那么number是全局变量或类似的变量吗)?这是合法的代码/程序吗?

第二种情况,让我们来看一下下面的代码:main.c:

#include 
#include 
#include "functions.h"
int main( void )
{
    printf( "Num = %d\n", number );
    printNumber();
    return 0;
}

functions.c:

#include 
#include 
#include 
#include "functions.h"
void printNumber( void )
{
    printf("Number = %d\n", number );
}

functions.h:

#ifndef FUNCTIONS
#define FUNCTIONS
extern int number;
extern void printNumber( void );
#endif // FUNCTIONS

这里程序将无法编译,因为会出现“undefined reference to number”的错误。

这迫使我在main中声明number:

#include 
#include 
#include "functions.h"
int number;
int main( void )
{
    printf( "Num = %d\n", number );
    printNumber();
    return 0;
}

这是正确的方式,为什么呢?

最后,为什么对于void printNumber( void )也不适用extern关键字呢?我看到无论有没有extern关键字,它都能正常工作。

0
0 Comments

在上述内容中,问题的出现是因为在头文件中定义变量时,只有在没有使用extern关键字的情况下才起作用。解决方法是在头文件中添加宏定义,并在主文件中使用宏来声明变量,这样在主文件编译时会为变量分配存储空间,而在其他源文件中,变量将被声明为extern。这样可以使变量只在主文件中可见,而在其他源文件中不可见。如果需要在主文件中使用在头文件中定义的变量,可以在主文件中重新定义这个变量,并使用static关键字来限制其作用范围。然而,需要注意的是,如果在头文件中重新定义这个变量,就会出现错误:static declaration of ‘number’ follows non-static declaration。因此,应该只在主文件中重新定义变量,而不再在头文件中进行定义。

0
0 Comments

问题的出现原因是在头文件中定义了变量,这意味着包含该头文件的每个翻译单元都会有该变量的定义。然而,这是不允许的,因为你只能在所有翻译单元中分散定义一个变量。

解决这个问题的方法是在头文件中声明变量,而不是定义变量。使用关键字extern标记它为声明而不是定义,编译器将知道该变量在其他地方定义。

然后你当然需要在一个单独的源文件中进行定义。在一个单一的源文件中进行定义,比如:

int number;

这就是你在最后一个变体中做的事情。

很多工具链和我认为posix允许多个定义...

所以这意味着如果我在main中声明int number,在functions.c中也不需要再声明了吗?这对函数也一样吗?

是的,如果你在functions.c中显式定义了它,你将面临多个定义的问题。对于函数也是一样的。

从未听说过 tentative definitions?

所以这意味着如果我在头文件中对所有变量和函数使用extern关键字,就没有问题了。谢谢。

函数默认是extern的,不需要显式指定。你可以通过将它们声明为static来使它们“局部”于翻译单元(.c文件)。

我明白了。很遗憾我不能为这个问题点赞,因为声望不到15。

不,没关系,因为第一段已经是错的。

extern void f(void);和void f(void);之间有一些微小的区别。第一个是声明,第二个是原型。

第一个只是声明,还是声明和原型都包括在内。我指的是它在头文件中的存在。

0