简体   繁体   English

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

[英]Confusion between declaration and definition of a variable in C

I am new to C and I experience some confusion between the declaration and definition of a variable. 我是C的新手,我在变量的声明和定义之间经历了一些混淆。 Another thing I would like to know is if the following is true: 我想知道的另一件事是如果以下情况属实:

"Declaration appears many times and definition comes once." “宣言多次出现,定义一次。”

Also: 也:

int x; 

Is this a declaration only? 这只是一个声明吗? Since memory is allocated for x then why isn't this a definition instead of a declaration? 由于内存是为x分配的,为什么这不是一个定义而不是声明?

Simply writing int x; 只需编写int x; at either global scope or local scope, is both a declaration and definition. 无论是全局范围还是局部范围, 都是声明和定义。 Typically, the declaration tells the compiler "This variable will exist, at some point, under this name, so you can use it." 通常,声明告诉编译器“此变量将在某个时候以此名称存在,因此您可以使用它”。 The definition tells the compiler to actually arrange for the variable to be created - obviously this can only happen once. 该定义告诉编译器实际安排要创建的变量 - 显然这只能发生一次。

Typically the way you'll use this is by putting in a header file: 通常,您使用此方法的方法是输入头文件:

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

extern int bar; // Declare a variable bar

#endif

And in a single source file 而在一个源文件

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

If you were to define bar in multiple files, you would get an error; 如果要在多个文件中定义条形,则会出现错误; you can't create the variable twice. 你不能两次创建变量。 But you do have to tell the compiler about it in every source file you use bar in. Hence the extern declaration. 但是,你必须告诉它你使用每个源文件编译bar中。因此, extern声明。

The precise semantics are defined in §6.9.2 of the C standard and can be summarized as follows: 精确语义在C标准的第6.9.2节中定义,可归纳如下:

  • When a variable is declared at file scope with an initializer, it is an external definition . 当使用初始化程序在文件范围声明变量时,它是外部定义 (§6.9.2/1) (§6.9.2/ 1)
  • When a variable is declared at file scope without an initializer, and without a storage-class specifier or with the static storage-class specifier, it is a tentative definition . 如果在没有初始化程序的情况下在文件范围内声明变量,并且没有存储类说明符或使用static存储类说明符,则它是一个暂定的定义 If the translation unit (file) has one or more tentative definitions and no external definition , the compiler automatically adds a true file scope declaration at the end of the translation unit, with a zero initializer. 如果转换单元(文件)具有一个或多个暂定定义而没有外部定义 ,则编译器会自动在转换单元的末尾添加一个真正的文件范围声明,并使用零初始值设定项。 (§6.9.2/2) (§6.9.2/ 2)

What this means is that, strictly speaking, int x; 这意味着严格地说, int x; is not a definition; 不是定义; but it automatically creates a definition if and only if there is no other definition with an initializer, and no static definition (this third case is undefined behavior due to linkage disagreement per §6.2.2/7) 但是当且仅当没有初始化程序的其他定义且没有static定义时,它会自动创建定义(由于链接不一致,第3种情况是未定义的行为,根据§6.2.2/ 7)

Note that extern int x; 注意extern int x; is not an external definition . 不是外部定义 It is a declaration with an extern storage class specifier. 它是一个带有extern存储类说明符的声明。 As such, extern int x; 因此, extern int x; alone does not cause a definition to be created, but if you have both: 单独不会导致创建定义,但如果您同时具有:

extern int x;
int x;

Then you will end up having a definition created at some point in the file. 然后,您将最终在文件中的某个位置创建定义。

It is also, technically speaking, legal to do this: 从技术上讲,这也是合法的:

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

In this case, the int x; 在这种情况下, int x; in the middle is superfluous and has no effect. 在中间是多余的,没有任何影响。 That said, this is poor form, as it's confusing in this case where the actual definition is. 也就是说,这是一种糟糕的形式,因为在实际定义的情况下这是令人困惑的。

This isn't something you see too much in C, but it works like this: 这不是你在C中看得太多的东西,但它的工作原理如下:

In a header file, you can have a line like this: 在头文件中,您可以使用如下行:

extern int x; //declaration

Because of the extern modifier, this tells the compiler that there is an int named x somewhere . 由于extern修饰符,这告诉编译器在某处有一个名为x的int。 The compiler doesn't allocate space for it - it just adds int x to the list of variables you can use. 编译器不为它分配空间 - 它只是将int x添加到您可以使用的变量列表中。 It'll only allocate space for x when it sees a line like this: 当它看到像这样的一行时,它只会为x分配空间:

int x; //definition

You can see that because only the int x; 你可以看到因为只有int x; line changes your executable, you can have as many extern int x; line更改你的可执行文件,你可以拥有尽可能多的extern int x; lines as you feel like. 你想要的线条。 As long as there's only int x; 只要只有int x; line, everything will work like you want it to - having multiple declarations doesn't change a thing. 行,一切都会像你想要的那样工作 - 拥有多个声明不会改变一件事。

A better example comes from C++ (sorry if this is a C-only question - this applies to struct s as well, but I don't know the syntax off the top of my head): 一个更好的例子来自C ++(对不起,如果这是一个只有C的问题 - 这也适用于struct s,但我不知道我头脑中的语法):

class Pineapple; //declaration

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

This declaration tells the compiler that there's a class called "Pineapple". 声明告诉编译器有一个名为“Pineapple”的类。 It doesn't tell us anything about the class (how big it is, what its members are). 它没有告诉我们关于班级的任何信息(它有多大,它的成员是什么)。 We can use pointers to Pineapples now, but we can't yet have instances - we don't know what makes up a Pineapple, so we don't know how much space an instance takes up. 我们现在可以使用指向Pineapples的指针,但是我们还没有实例 - 我们不知道Pineapple的构成是什么,所以我们不知道实例占用了多少空间。

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;

After a definition , we know everything about the class, so we can have instances, too. 定义之后 ,我们知道关于类的所有内容,因此我们也可以拥有实例。 And like the C example, you can have multiple declarations, but only one definition. 和C示例一样,您可以有多个声明,但只有一个定义。

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM