C中变量的声明和定义之间的混淆

时间:2011-03-01 06:43:40

标签: c variables

我是C的新手,我在声明和变量定义之间遇到了一些混淆。另一件我想知道的是,如果以下情况属实:

  

“宣言多次出现,定义一次。”

此外:

int x; 

这只是一个声明吗?由于内存是为x分配的,那为什么这不是一个定义而不是一个声明?

2 个答案:

答案 0 :(得分:8)

只需在全局范围或本地范围内编写int x;一个声明和定义。通常,声明告诉编译器“此变量将在某个时候以此名称存在,因此您可以使用它”。该定义告诉编译器实际安排要创建的变量 - 显然这只能发生一次。

通常,您使用此方法的方法是输入一个标题文件:

// Foo.h
#ifndef FOO_H
#define FOO_H // make sure structs aren't redefined

extern int bar; // Declare a variable bar

#endif

并在单个源文件中

#include "foo.h"
int bar; // Define bar

如果要在多个文件中定义条形,则会出现错误;你不能两次创建变量。但是你必须在你使用bar的每个源文件中告诉编译器它。因此extern声明。

精确语义在C标准的第6.9.2节中定义,可归纳如下:

  • 当使用初始化程序在文件范围内声明变量时,它是外部定义。 (§6.9.2/ 1)
  • 如果在没有初始化程序且没有存储类说明符或使用static存储类说明符的文件范围内声明变量,则它是暂定定义。如果翻译单元(文件)具有一个或多个暂定定义且没有外部定义,则编译器会自动在翻译单元的末尾添加真正的文件范围声明,零初始化器。 (§6.9.2/ 2)

这意味着,严格来说,int x;不是定义;但它会自动创建一个定义当且仅当没有初始化程序的其他定义,并且没有static定义时(由于链接不一致,第三种情况是未定义的行为,根据§6.2.2 / 7)

请注意,extern int x;不是外部定义。它是一个带有extern存储类说明符的声明。因此,仅extern int x;不会导致创建定义,但如果同时具有两者:

extern int x;
int x;

然后,您将最终在文件中的某个位置创建定义。

从技术上讲,这也是合法的:

extern int x;
int x;
int x = 42;

在这种情况下,中间的int x;是多余的,没有任何效果。也就是说,这是一种糟糕的形式,因为在这种情况下实际定义是令人困惑的。

答案 1 :(得分:7)

这不是你在C中看得太多的东西,但它的工作原理如下:

在头文件中,您可以使用以下行:

extern int x; //declaration

由于extern修饰符,这告诉编译器有一个名为x 的int 。编译器不为它分配空间 - 它只是将int x添加到您可以使用的变量列表中。当它看到像这样的一行时,它只会为x分配空间:

int x; //definition

您可以看到,因为只有int x;行更改了您的可执行文件,您可以拥有尽可能多的extern int x;行。只要只有int x;行,一切都会像你想要的那样工作 - 多个声明不会改变一件事。

一个更好的例子来自C ++(对不起,如果这是一个只有C的问题 - 这也适用于struct s,但我不知道我的头脑中的语法:

class Pineapple; //declaration

Pineapple* ptr;  //this works
Pineapple pine;  //this DOES NOT work

声明告诉编译器有一个名为“Pineapple”的类。它没有告诉我们关于班级的任何信息(它有多大,它的成员是什么)。我们现在可以使用指向Pineapples的指针,但是我们还没有实例 - 我们不知道菠萝的构成是什么,所以我们不知道实例需要多少空间。

class Pineapple
{
public:
    int ounces;
    char* name;
}; //definition

Pineapple* ptr;   //still works
Pineapple pine;   //this works now too!
//we can even get at member variables, 'cause we know what they are now:
pine.ounces = 17;

定义之后,我们知道关于类的所有内容,因此我们也可以拥有实例。和C示例一样,您可以有多个声明,但只有一个定义。

希望这有帮助!