C编程中前向声明的意义是啥?
Posted
技术标签:
【中文标题】C编程中前向声明的意义是啥?【英文标题】:What is the significance of forward declaration in C programming?C编程中前向声明的意义是什么? 【发布时间】:2016-01-29 12:29:11 【问题描述】:我现在正在通过 Zed A. Shaw 的 Learn C the Hard Way 学习 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_it
和print_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");
前向声明真的很重要且不可避免吗?
【问题讨论】:
“前向声明真的很重要且不可避免吗?” - 是的,一直,我并不是说你必须一直转发声明,但这是非常普遍和不可避免的,基本上每次你在两个对象之间有一个“循环关系”时,即使他们经常需要它在同一源中声明 如果func1
调用func2
,而func2
调用func1
会怎样? (但重点是头文件和库。)
你的方法如何绕过这个?而不是使用“短方法签名”声明,而是在那里声明和定义整个函数。
想象一下你有一个更大的项目。将所有代码放在一个 .c
文件中绝对是一场噩梦,因此您通常会将其拆分为多个源文件。所以现在,要从b.c
中调用a.c
中定义的myFunc
,您需要一个前向声明(通常在头文件中)。
哇,真的很多投入。由于我是初学者,我无法真正理解这里的所有论点,但我确实知道这有什么用处。谢谢。
【参考方案1】:
只要你的调用图是循环的,函数的前向声明是不可避免的;也就是说,只要您在函数之间进行(直接或间接)递归。
如果您想将程序分成多个翻译单元,它们很有用,因为它们允许分离声明和函数定义(将声明放在 .h
标头和定义中)在.c
文件中)。
【讨论】:
我知道具有 1024 字节内存的计算机受益于前向声明,因为它们可以一次编译 C,但是为什么,哦,为什么,我今天必须在同一个源文件中预先声明函数?我有千兆字节的内存可用?! @Gunchars 说得好; C++ 设法解析可能在其函数体内相互引用的内联成员函数。在这一点上,它只是历史惯性;没有一个实现可以在不被指责为无端不兼容的情况下进行更改,标准委员会对进行彻底的更改持谨慎态度是可以理解的。也许它仍然会发生;毕竟我们现在可以在函数开头声明变量了。【参考方案2】: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;
...
【讨论】:
【参考方案3】:您应该按照有意义的顺序声明函数。这应该在您遵循的编码风格文档中进行描述。常见设计的一个例子是:
包含所有公开可用函数声明的 h 文件。 顶部包含所有私有函数声明的 c 文件。 然后在同一个 c 文件中遵循公共函数的函数定义。 然后在该 c 文件的末尾,私有函数的函数定义。除了样式和设计问题之外,如果在函数调用之前根本没有可见的原型,那么古老的 C 版本将开始“组成”函数参数和返回类型。
【讨论】:
【参考方案4】:前向声明取决于程序的需要。程序员可以自己设计。
理解意义:在C和C++中,上面一行代表一个 函数的前向声明,是函数的原型。 处理此声明后,编译器将允许 程序代码在其余部分引用实体 printThisInteger 该程序。必须在某处提供函数的定义 (相同的文件或其他文件,这将是由 链接器正确匹配对特定函数的引用 或具有定义的几个目标文件,这些文件必须是唯一的,在 另一个):
【讨论】:
如果你要从***复制和粘贴一段,你至少可以提供一个链接到你抄袭的Forward declaration article。以上是关于C编程中前向声明的意义是啥?的主要内容,如果未能解决你的问题,请参考以下文章