C - >标题&变量

时间:2016-01-08 20:37:51

标签: c variables header

C中的头文件可以包含变量吗?

我是编程的初学者;从C开始,我知道精确度的重要性,特别是在学习过程的第一步中

3 个答案:

答案 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.oblurga.omain.o。每个目标文件都有自己唯一的foo变量副本。但是,当我们使用

将它们构建为单个可执行文件时
gcc -o foo main.o bar.o blurga.o

链接器非常聪明,可以意识到foo的那些单独声明是指引用同一个对象(标识符foo在这些转换单元中具有外部链接 )。因此,foo初始化为main的{​​{1}}与5设置为foo的{​​{1}}相同,blurga相同10 foobar打印出来。

但是,如果您将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关键字告诉编译器标识符引用的对象是在其他地方定义的。