Skip to content

Declaration and definition

在文章language中,我们已经总结了,我们作为programmer在使用programming language来“描述”世界,这里的描述,使用更加专业的属于是declaration 和 definition,大多数programming language都会涉及到definition的概念,像c和c++这样的语言,区分declaration和definition,而像python和C++这样的语言,则不区分,是否区分,有利有弊,后面我们会进行分析。

What declaration and definition mean for compiler?

Example

有代码如下: a.c

void test_a()//定义函数test_a
{
     return;
}

b.c

void test_a();

void test_b()
{
    test_a();    // 由于上面已经声明了,所以可以使用 
}

void main()
{
    test_b();
}

编译命令如下

gcc a.c b.c -o b

按照这种写法是可以正确编译出可执行文件b的。

如果我将编译命令修改为如下形式:

gcc b.c -o b

则编译器会报如下错误:

/tmp/cc91umxf.o:在函数‘test_b’中:
b.c:(.text+0xa):对‘test_a’未定义的引用
collect2: 错误:ld 返回 1

这是链接错误。

也就是找不到函数test_a的定义。

这个问题引发了我这样的思考:对于编译器而言,声明和定义分别意味着什么?编译器对函数声明,函数定义的处理和对变量声明,变量定义的处理是相同的吗?

显然是不相同的。

函数声明对于编译器意味着什么

如果在b.c中将函数test_a的声明去除掉的话,再进行编译,我发现函数也能够编译通过,并且能够正确执行。

Thoughts

只有definition才会被编译object file中,declaration仅仅由于grammar检查。

Declaration

wikipedia Declaration (computer programming)

In computer programming, a declaration is a language construct that specifies properties of an identifier: it declares what a word (identifier) "means". Declarations are most commonly used for functions, variables, constants, and classes, but can also be used for other entities such as enumerations and type definitions. Beyond the name (the identifier itself) and the kind of entity (function, variable, etc.), declarations typically specify the data type (for variables and constants), or the type signature (for functions); types may also include dimensions, such as for arrays. A declaration is used to announce the existence of the entity to the compiler; this is important in those strongly typed languages that require functions, variables, and constants, and their types to be specified with a declaration before use, and is used in forward declaration. The term "declaration" is frequently contrasted with the term "definition", but meaning and usage varies significantly between languages; see below.

Declarations are particularly prominent in languages in the ALGOL tradition, including the BCPL family, most prominently C and C++, and also Pascal. Java uses the term "declaration", though Java does not have separate declarations and definitions.

wikipedia Forward declaration

In computer programming, a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.

It is required for a compiler to know certain properties of an identifier (size for memory allocation, data type for type checking, such as type signature of functions), but not other details, like the particular value it holds (in case of variables or constants) or definition (in the case of functions). This is particularly useful for one-pass compilers and separate compilation.

Forward declaration is used in languages that require declaration before use; it is necessary for mutual recursion in such languages, as it is impossible to define such functions (or data structures) without a forward reference in one definition: one of the functions (respectively, data structures) must be defined first. It is also useful to allow flexible code organization, for example if one wishes to place the main body at the top, and called functions below it.

In other languages forward declarations are not necessary, which generally requires instead a multi-pass compiler and for some compilation to be deferred to link time. In these cases identifiers must be defined (variables initialized, functions defined) before they are used in execution, but do not need to be defined before they are used in source code for compilation or interpretation: identifiers do not need to be immediately resolved to an existing entity.

NOTE: 显然forward declaration是compiler需要的,而linker是不需要的