问题
I'm trying to learn C language for embedded systems. At the moment I'm learning the basics and couldn't find an answer to one of a fundamental question. When I wrote a simple C program I declared a function called maximum() in three ways. I will explain it by the following examples:
1-) Here in the below program the function is declared outside and before the main:
#include <stdio.h>
int maximum(int x, int y)
{
int z;
z = (x >= y) ? x : y;
return z;
}
int main(void)
{
int result = maximum(30, 50);
printf("%d", result);
return(0);
}
2-) And now below the function is declared outside and after the main:
#include <stdio.h>
int main(void)
{
int result = maximum(30, 50);
printf("%d", result);
return(0);
}
int maximum(int x, int y)
{
int z;
z = (x >= y) ? x : y;
return z;
}
3-) And finally below the function is declared inside the main:
#include <stdio.h>
int main(void)
{
int maximum(int x, int y)
{
int z;
z = (x >= y) ? x : y;
return z;
}
int result = maximum(30, 50);
printf("%d", result);
return(0);
}
I tried all those above and all executes without error. Is there any reason to prefer one to the others?
回答1:
In standard C since C99, it is necessary to declare functions before you call them. This tells the compiler what type to expect of the return value, how many arguments it should pass, how it might need to convert them to correctly match the function's parameter types. That declaration does not need to be a definition of the function, however, and frequently it isn't.
Your (1) is fine in this regard, but your (2) is non-conforming. However, (2) happens to have return and parameter types that are consistent with older C expectations for calling an undeclared function, and many compilers will accept it and do the right thing with it under some circumstances.
Your (3) is non-conforming in a different way: C does not allow nested functions. You may put a function declaration inside another function, though there is little advantage to this, but not a whole function definition. One compiler family I know does accept that as an extension, and maybe others do, too, but under no circumstances should you rely on that.
Thus, of the three alternatives presented, (1) is the only one you should use. If you want to have more freedom to place the maximum()
function then provide a forward declaration, with prototype, near the top of the file:
(4)
#include <stdio.h>
// Forward declaration, including prototype:
int maximum(int x, int y);
int main(void)
{
int result = maximum(30, 50);
printf("%d", result);
return(0);
}
int maximum(int x, int y)
{
int z;
z = (x >= y) ? x : y;
return z;
}
回答2:
Option 1 is valid and it works, but it tends to hide the main
function at the end of your program.
Option 2 is not valid starting with C99 where there's no "default int
" anymore.
Option 3 is not valid although many compilers support it.
What I would suggest is a mix of options 1 and 2. Declare the function prototype before main
and define it later in the file:
#include <stdio.h>
int maximum(int x, int y);
int main(void)
{
int result = maximum(30, 50);
printf("%d", result);
return(0);
}
int maximum(int x, int y)
{
int z;
z = (x >= y) ? x : y;
return z;
}
回答3:
This is probably a duplicate, but here goes. For a function defined in the same file where main
is defined:
If you define it before
main
, you only have to define it; you don't have to declare it and separately define it.If you define it after
main
, you have to put a matching prototype declaration beforemain
. But the advantage is that your source file then reads more naturally: a reader can start at the top and see whatmain
does, without getting distracted by a bunch of utility functions.If you want to define it inside
main
, you're stuck, because standard C doesn't have nested functions. (Some compilers do offer it as an extension.)
For a function defined in some other source file than the file where main
is defined, you just need the function prototype declarations before main
-- typically/preferably/ideally via an #include
file.
In the end this is a question of style, without a single, objective answer (other than that nested functions aren't Standard). Different programmers can and do make different choices. If your company or other institution has a style guide, it might weigh in on this question. Me, I usually prefer to put main
first and function definitions below it, but I'm not dogmatic about it.
回答4:
Basically if you declare functions inside another function, which main is, it's only available in that scope. So for example, if you want to call maximum
from another file, you won't be able to do it.
Declaring functions outside main is preferred when you want to call it externally and also very beneficial in terms of code readability and maintainability.
回答5:
The safest way to write C is to always provide a function prototype.
But if you're coding to a C "dialect" (C89, for example) where function prototypes are not required, one huge advantage of prototypes - getting the type of the return value right. If you change your original code that doesn't have a prototype so the return value is not int
, the compiler will (depending on the version of the C standard you are compiling against) assume it returns int
and not what the function actually returns. For example if you change your code to:
#include <stdio.h>
int main(void)
{
int *result = maximum(30, 50);
printf("%d", *result);
return(0);
}
/* now returns int * and not
just int */
int *maximum(int x, int y)
{
static int z;
z = (x >= y) ? x : y;
return &z;
}
and serious problems can arise.
Why?
Because, depending on your "dialect" of C based upon your exact compiler and the arguments you pass it (for example, you wind up applying the C89 standard for some reason), calling a function without a prototype will cause the compiler to assume the function returns int
even though it actually returns int *
. See Calling a C Function without Prototype and Are prototypes required for all functions in C89, C90 or C99? (and follow the linked questions) for a full discussion.
The TLDR; safe answer to "Are function prototypes required in C?" is "Not always. But if you don't have one, you can get some serious problems."
So, in this example, even though maximum()
is defined to return an int *
, the compiler assumes it actually returns int
.
That won't work well. It can work silently, it can fail silently, it can fail obviously.
See Do I cast the result of malloc? for a specific discussion with respect to malloc()
.
Extra warning
And never, ever, ever provide a prototype for a function that's defined in the old K&R style:
int function( a, p )
int a;
char *p
{
....
}
Doing that will break things even worse. Old K&R style functions expect all their arguments that have been passed have undergone default argument promotion. That's the same thing that happens to the variable arguments passed to functions like printf()
. But if you provide a function prototype, the arguments will not be promoted. If you pass a float
to a function expecting its to have undergone promotion, the function will expect a double
, for example.
So if you run into old, old K&R style C code, you won't be helping things and will actually cause all kinds of problems if you provide prototypes for all the function calls - unless you rewrite the function definitions also.
回答6:
From working with large projects (1000+ files), I think it is more important to make it easier for read the files. This implies placing the 'major' functions of a module (using the 'public' API, or main
) at the top. It make it easier for readers to find the 'beef'.
Following this logic, other functions (maximum in this case), should be declared before the 'major' functions (to get type-checking, clean build), and placed toward the bottom of the file.
// header file describing the 'public' API
#include "header.h"
static int maximum(int x, int y);
// Public API
int main(int argc, char **argv)
{
...
maximum(...);
}
char *other_function(...)
{
...
}
// Static "private" functions
static int maximum(int x, int y)
{
...
}
回答7:
I would personally say option 2 but you need to declare it above int main void
Reasoning behind this is at the moment the code is very simple but as you work on larger projects you don't want to have to scroll pages and pages to get to your main function
回答8:
I do not advise to use option 3, option 1 is the best as I use it often... Anyways main() is the entry point of your application... I do not think that any of the methods 1 or 2 affect the performance of your application... If you use method 2 its good you prototype it since according to C99 standard its invalid and compliers generate warning for implicit declaration . But when designing code readability should be a paramount concern as we even the programmers could get lost in maze of confusion... I advise you to put your functions dedicated to a particular task in a separate header file Happy Coding !!!
来源:https://stackoverflow.com/questions/58994523/are-there-advantages-of-declaring-functions-before-after-or-inside-main