I am now learning C programming through Learn C the Hard Way by Zed A. Shaw. There is this code (taking from his website):
#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;
}
Don't we just can code it like this (put the can_print_it
and print_letters
functions at the top and remove the need for forward declaration):
#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");
}
Is there really times when the forward declaration is important and unavoidable?
Forward Declaration refers to the beforehand declaration of the syntax or signature of an identifier, variable, function, class, etc. prior to its usage (done later in the program). In C++, Forward declarations are usually used for Classes.
The Google style guide recommends against using forward declarations, and for good reasons: If someone forward declares something from namespace std, then your code exhibits undefined behavior (but will likely work).
Forward reference is when you declare a type but do not define it. It allows you to use the type by pointer (or reference for C++) but you cannot declare a variable. This is a way to say to the compiler that something exists.
A "declaration" establishes an association between a particular variable, function, or type and its attributes. Overview of Declarations gives the ANSI syntax for the declaration nonterminal. A declaration also specifies where and when an identifier can be accessed (the "linkage" of an identifier).
Forward declarations of functions are unavoidable whenever your call graph is cyclic; that is, whenever you have (direct or indirect) recursion between functions.
They are useful if you want to separate your program into more than one translation unit, as they allow separation of declaration and definition of functions (placing the declaration in a .h
header and the definition in a .c
file).
Forward declarations of functions in C typically have two different uses.
The header of exported functions are declared in a header file which is included in a client module.
In mutual recursion two functions call each other repeatedly. Without a forward declaration one of the two functions will be undeclared in the body of the other.
Example:
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);
}
With a function pointer though, we can do without a forward declaration:
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;
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With