C编程中前向声明的意义是什么?

时间:2016-01-29 12:29:12

标签: c forward-declaration

我现在通过Zed A. Shaw的“学习C艰难之路”学习C编程。这段代码(来自他的网站):

#include <stdio.h>
#include <ctype.h>

// forward declarations
int can_print_it(char ch);
void print_letters(char arg[]);

void print_arguments(int argc, char *argv[])
{
    int i = 0;

    for(i = 0; i < argc; i++) {
        print_letters(argv[i]);
    }
}

void print_letters(char arg[])
{
    int i = 0;

    for(i = 0; arg[i] != '\0'; i++) {
        char ch = arg[i];

        if(can_print_it(ch)) {
            printf("'%c' == %d ", ch, ch);
        }
    }

    printf("\n");
}

int can_print_it(char ch)
{
    return isalpha(ch) || isblank(ch);
}


int main(int argc, char *argv[])
{
    print_arguments(argc, argv);
    return 0;
}

我们不能像这样编写代码(将can_print_itprint_letters函数置于顶部并删除前向声明的需要):

#include <stdio.h>
#include <ctype.h>

int can_print_it(char ch)
{
    return isalpha(ch) || isblank(ch);
}

void print_letters(char arg[])
{
    int i = 0;

    for(i = 0; arg[i] != '\0'; i++) {
        char ch = arg[i];

        if(can_print_it(ch)) {
            printf("'%c' == %d ", ch, ch);
        }
    }

    printf("\n");
}

有时候前瞻性声明很重要且不可避免吗?

4 个答案:

答案 0 :(得分:10)

当您的调用图是循环的时,函数的前向声明是不可避免的;也就是说,只要你在函数之间进行(直接或间接)递归。

如果您希望将程序分成多个翻译单元,它们有用,因为它们允许分离声明和函数定义(将声明放在.h标题中.c文件中的定义。

答案 1 :(得分:6)

C中函数的前向声明通常有两种不同的用法。

模块

导出函数的标头在头文件中声明,该文件包含在客户端模块中。

相互递归

在相互递归中,两个函数重复相互调用。如果没有前瞻性声明,则两个函数中的一个将在另一个函数的主体中未声明。

示例:

int Odd(int n);

int Even(int n)
{
    return (n == 0)? 1: Odd(n - 1);
}

int Odd(int n)
{
    return (n == 0)? 0: Even(n - 1);
}

使用函数指针,我们可以不使用前向声明:

int (*odd)(int n);

int Even(int n)
{
    return (n == 0)? 1: odd(n - 1);
}

int Odd(int n)
{
    return (n == 0)? 0: Even(n - 1);
}

void Init(void)
{
    odd = Odd;
    ...
}

答案 2 :(得分:3)

您应该按照有意义的顺序声明函数。这应该在您遵循的编码样式文档中描述。常见设计的一个例子是:

  • 包含所有公开可用函数声明的h文件。
  • 包含所有私有函数声明的c文件。
  • 然后在同一个c文件中跟随公共函数的函数定义。
  • 然后在该c文件的末尾,私有函数的函数定义。

除了风格和设计方面的问题,C的古老版本将开始构成&#34;函数参数和返回类型,如果在函数调用之前根本没有原型可见。

答案 3 :(得分:2)

前向声明符合计划的需要。程序员可以自己设计它。

  

理解其意义:在C和C ++中,上面的行表示一个   函数的前向声明,是函数的原型。   处理完这个声明后,编译器会允许   程序代码在其余部分引用实体printThisInteger   该程序。必须在某处提供函数的定义   (同一文件或其他文件,它将由...负责   链接器在一个中正确匹配对特定函数的引用   或几个具有定义的目标文件,其中必须是唯一的   另一个):