为什么函数声明在源文件顶部附近?
我正在通过 K & 工作。 R学习编程。到目前为止进展顺利,但我不清楚 1.8 节(函数)中的一行代码的作用。
在第 1.8 节中,作者向您展示了如何创建一个函数来计算一个整数的另一个整数次方。
我粘贴了下面的代码,正如书中所写的那样。一切输出都很好。但我不知道为什么他们在顶部添加了这一行:
int power(int m, int n);
除了说该程序将计算整数 m 的 n 次方之外,书中没有提及这一点。如果我从代码中删除该行,程序仍然会按预期输出。
如果我理解正确的话,该行
int power(int base, int n)
创建函数,下面的大括号定义该函数。然后main下面的大括号调用函数来输出图表。
所以这一切似乎都有道理。但我不明白最上面一行是做什么的。
这可能是无关紧要的,但似乎更有可能我错过了一些东西。谁能告诉我为什么会有这条线?
#include <stdio.h>
int power(int m, int n);
/* test power function */
main()
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, power(2,i), power(-3, i));
return 0;
}
/* power: raise base to n-th power; n >= 0 */
int power(int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
I'm working through K & R to learn programming. Going well so far, but I'm unclear about the role of a line of code from section 1.8 (functions).
In section 1.8, the authors show you how to create a function to raise one integer to the power of another integer.
I've pasted the code below, as it was written in the book. Everything outputs fine. But I don't know why they've included this line at the top:
int power(int m, int n);
The book doesn't mention it, apart from saying that the program will raise integer m to the power n. If I remove the line from the code, the program still outputs as it should.
If I understand this correctly, the line
int power(int base, int n)
creates the function, and the braces underneath define the function. Then the braces under main call the function to output the chart.
So all that seems to make sense. But I don't see what the very top line does.
It could be extraneous, but it seems far more likely that I'm missing something. Can anyone enlighten me as to why that line is there?
#include <stdio.h>
int power(int m, int n);
/* test power function */
main()
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, power(2,i), power(-3, i));
return 0;
}
/* power: raise base to n-th power; n >= 0 */
int power(int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
第一行是函数的声明。底部的代码块是函数的定义。
从 1999 版 ISO C 标准开始,调用没有可见声明的函数是非法的(违反约束);声明必须在调用之前。
对于像这样的简单程序,您可以在
main()
定义之前编写power()
的完整定义(因为定义还提供声明),但对于更复杂的情况(例如递归调用),您通常需要提供单独的声明。对于较大的程序,通常将所有函数声明收集在头文件(例如
foo.h
)中,并将相应的定义收集在源文件(>foo.c
,例如)。#include "foo.h"
指令用于使声明在其他文件中可见。你会在本书后面看到这种事情。(在 1990 年及更早版本的 C 中,即 K&R2 所涵盖的内容,在某些情况下您可以在没有可见声明的情况下调用函数 - 但无论如何提供显式声明仍然是一个非常好的主意。)
顺便说一句,主程序的声明实际上应该是
int main(void)
而不仅仅是main()
。术语:“原型”是指定参数类型的函数声明。
(参数名称在定义中是必需的,但在独立声明中是可选的。)
作为一种特殊情况,没有参数的函数原型使用
(void)
,因为空括号已经意味着非原型声明。所以int main(void)
是一个原型,但int main()
不是。非原型声明是“过时的”,这意味着理论上它们可以从未来的语言标准中删除。但它们自 1989 年以来就已经过时了,即使在新的 2011 年 ISO C 标准中,委员会也认为不适合删除它们。
The first line is the declaration of the function. The block of code at the bottom is the definition of the function.
Starting with the 1999 version of the ISO C standard, it's illegal (a constraint violation) to call a function without a visible declaration; the declaration must precede the call.
For a simple program like this one, you could just write the full definition of
power()
before the definition ofmain()
(since a definition also provides a declaration), but for more complex cases (such as recursive calls) you often need to provide a separate declaration.For larger programs, it's common to collect all the function declarations in a header file (
foo.h
, for example), and the corresponding definitions in a source file (foo.c
, for example). A#include "foo.h"
directive is used to make the declarations visible in other files. You'll see that kind of thing later in the book.(In the 1990 and earlier versions of C, which is what K&R2 covers, there are cases where you can call a function without a visible declaration -- but it's still a very good idea to provide explicit declarations anyway.)
Incidentally, the declaration of the main program should really be
int main(void)
rather than justmain()
.Terminology: a "prototype" is a function declaration that specifies the types of the parameters.
(Parameter names are required in a definition, but optional in a standalone declaration.)
As a special case, a prototype for a function with no parameters uses
(void)
, since empty parentheses already mean a non-prototype declaration. Soint main(void)
is a prototype, butint main()
isn't.Non-prototype declarations are "obsolescent", meaning that they could in theory be removed from a future language standard. But they've been obsolescent since 1989, and even in the new 2011 ISO C standard the committee hasn't seen fit to remove them.
是
power
函数的原型形式的声明。函数声明告知编译器该函数具有的参数数量、函数参数的类型以及函数返回值的类型。在 C 中,在声明函数标识符之前不能使用它。
is a declaration of the
power
function in its prototype form. A function declaration informs the compiler of the number of parameters the function has, the type of the function parameters and the type of the function return value.In C you cannot use a function identifier before it has been declared.
这是一个前向声明,它使函数接口公开,因为该函数在
main()
下面实际实现之前使用。头文件,您
#include
提供了使可调用 API 公开的类似功能,但是代码通常在库中提供,而不是通过与此中相同的编译单元提供K&R 介绍章节的单文件示例。It's a forward declaration which makes the function interface public as the function is used before it is actually implemented below
main()
.Header files, which you
#include
provide a similar functionality of making the callable API public---but the code is then commonly supplied in a library rather than via the same compilation unit as it is here in this single-file example of the K&R Intro chapter.如果您不在顶部包含该行,则当程序达到主功率中的
power(2,i)
时,尚未声明。程序是从上到下读取的,通过将声明放在顶部,编译器知道“定义即将到来”。If you don't include that line at the top, when the program reaches
power(2,i)
in main power has not been declared yet. Programs are read from top to bottom, and by putting the declaration at the top, the compiler knows that "a definition is coming".该行只是函数原型。这是一个前向声明,它允许代码能够使用具有该签名的某些函数,该签名在所有内容链接在一起时都会存在。如果没有它,
main()
函数将尝试使用power()
函数,但编译器尚未意识到它,因为它实际上并未在稍后的函数中定义。源文件。That line is just the function prototype. It's a forward declaration that allows code to be able to use some function with that signature that will exist when everything is linked together. Without it, the
main()
function will attempt to use thepower()
function but the compiler is not aware of it yet since it isn't actually defined later in the source file.您所指的顶部那行是函数原型。它的唯一用途是让编译器可以检查您的工作,即通过传递正确的类型和参数数量来确保您正确使用该函数。这就是它的全部目的。这就是为什么你可以删除它并且代码仍然可以编译 - 通过删除它你所做的只是删除编译器的引用,这样它就无法检查你的工作。如果您确实删除了它,那么您可能会传递错误类型的参数并导致难以发现的运行时错误或程序崩溃。但是保留它可以让编译器在编译时标记此类错误,从而节省您的精力。为某人减轻一些悲伤是一件好事。
后来,在 C99 标准中,他们决定强制提供函数原型(或者首先定义函数)以便代码能够编译,从而迫使您让编译器检查您的工作。
That line at the top that you are referring to is a function prototype. The ONLY thing it is there for is so that the compiler can check your work, that is, to make sure you are using the function correctly by passing the right types and number of arguments. That's all it is for. That is why you can remove it and the code still compiles - all you are doing by removing it is removing the compiler's reference so it can't check your work. And if you do remove it, then there is the possibility that you could pass the wrong type of argument(s) and cause a hard to find run time error or program crash. But leaving it in allows the compiler to flag such an error at compile time saving you some grief. And saving someone some grief is a good thing.
Later, with the C99 standard, they decided to make it mandatory to provide a function prototype (or else define the function first) in order for the code to compile, thus forcing you to let the compiler check your work.