C中的头文件可以包含变量吗?
我是编程的初学者;从C开始,我知道精确度的重要性,特别是在学习过程的第一步中
答案 0 :(得分:1)
包含文件由预处理器完成,甚至在尝试编译代码之前完成文本替换 - 它将包含文件的内容放在将要传递给编译器的当前单元中。然后编译器会看到连接的输出,根本没有#include
指令。
据说,从技术上讲,你可以包含任何有效的C代码。
然而,好的做法是只有类型定义,#define
,函数声明(不是定义)和数据声明(不是 definitions )应该在标题中。函数声明也称为原型,仅指定函数签名(其返回类型,名称和参数)。数据声明与数据定义非常相似,但具有extern
存储类说明符,无法初始化:
extern int a; // declares "a" but does not define it
extern int a = 0; // defines "a" (initialisation requested), the extern is redundant
int a; // a tentative definition (no initialisation but "a" is zeroed)
为什么在头文件中定义函数和数据不受欢迎?因为在链接时,包含相同头文件的不同单元将定义相同的符号,链接器将看到某些符号的重复定义。
还要考虑标题是项目其余部分(世界?)的一种“公共”接口,并不是源文件中定义的每个函数都需要在那里声明。在源文件中拥有永远不会暴露给外部世界的内部类型和static
函数和数据是完全正常的。
答案 1 :(得分:0)
基本上在头文件中,我们可以声明变量指向只注明声明是允许的,不要定义
让我说清楚。
int a=10; // definition
extern int a; //declaration - it can be used in another file if u include this header file.
您还可以定义宏并在头文件中声明函数。
答案 2 :(得分:0)
是的,头文件可能包含变量声明,但您通常不希望这样做,因为它会随着时间的推移引入维护难题,尤其是当您的代码变得更大和更复杂时。理想情况下,函数应通过参数和返回值共享信息,而不是使用此类“全局”数据项。
有些时候你无法避免它;我没有做任何嵌入式编程,但我的理解是,由于空间和性能限制,使用全局变量在该域中相当普遍。
理想情况下,标题应限于以下内容:
但是假设你确实创建了一个带有变量声明的头文件,如下所示:
/**
* foo.h
*/
int foo;
并且您有几个源文件都包含该头文件 1 :
/**
* bar.c
*/
#include "foo.h"
void bar( void )
{
printf( "foo = %d\n", foo );
}
/**
* blurga.c
*/
#include "foo.h"
void blurga( void )
{
foo = 10;
}
/**
* main.c
*/
#include "foo.h"
int main( void )
{
foo = 5;
blurga();
bar();
return 0;
}
每个文件都将在文件范围(任何函数之外)包含foo
的声明。现在你单独编译每个文件
gcc -c bar.c
gcc -c blurga.c
gcc -c main.c
为您提供三个目标文件 - bar.o
,blurga.o
和main.o
。每个目标文件都有自己唯一的foo
变量副本。但是,当我们使用
gcc -o foo main.o bar.o blurga.o
链接器非常聪明,可以意识到foo
的那些单独声明是指引用同一个对象(标识符foo
在这些转换单元中具有外部链接 )。因此,foo
初始化为main
的{{1}}与5
设置为foo
的{{1}}相同,blurga
相同10
foo
那bar
打印出来。
但是,如果您将foo
的声明更改为
static int foo;
在foo.h
中并重建您的文件,那些单独的声明将不引用同一个对象;它们将保留三个独立且不同的对象,以使foo
初始化的main
不与foo
设置为{blurga
相同的10
1}},与foo
打印出来的bar
不同(foo
在每个翻译单元中都有内部链接)。
如果必须在多个翻译单元之间使用全局变量,我首选的样式是将头文件中的变量声明为extern
2
/**
* foo.h
*/
extern int foo;
然后在相应的.c文件中定义它
/**
* foo.c
*/
int foo;
因此,只有一个目标文件会创建一个foo
的实例,并且它的清晰您打算让其他翻译单元使用它。头文件中的声明对于共享变量不是必需的(foo
标识符具有外部链接,只需在任何函数之外的foo.c
中声明并且没有static
}关键字),但没有它,没有其他人可以确定你意味着它是否可见或者你只是马虎。
修改强>
请注意,标题 不包含在文件顶部;你可能是反常的,并在函数体中放入#include
指令
void bar( void )
{
#include "foo.h"
// do stuff with foo
}
这样int foo;
将是函数的本地函数,尽管这可能会让你的同事们受到殴打。我必须维护代码,有人这样做,25年后它仍然让我做噩梦。
<小时/> 1。 请不要写这样的代码;它只是为了说明联系的概念 2.
extern
关键字告诉编译器标识符引用的对象是在其他地方定义的。