The Divide Principle
Variable sharing
In the previous section, we divided the program into multiple files with a minimal structure.
However, we could only share functions; we did not share variables.
If you develop using multiple source files,
However, there will also be a need to share variables and constants, not just functions.
The method in the previous chapter does not allow for sharing variables.
For example, if you declare a variable within a header file, like this:
I'm getting an error saying 'declaration is redundant' and it won't compile.
To better understand this error, you need to understand the meaning of declarations.
So far, we've been using the term declare to describe both functions and variables.
Actually, declarations have two kinds of functionality.
When variables or functions are declared, the compiler memorizes their names and shapes.
This is a feature called the Declaration.
And simultaneously, the compiler actually creates variables and functions.
This is a function called definition.
Previously, we always performed declaration and definition simultaneously with these variables.
Declarations merely inform the compiler about the form of variables and functions.
As long as the form is the same, it doesn't matter how many times you declare it.
However, in terms of the definition, this creates concrete instances of functions and variables.
It results in an error because it becomes difficult to distinguish between multiple instances of the same function or variable.
However, we could only share functions; we did not share variables.
If you develop using multiple source files,
However, there will also be a need to share variables and constants, not just functions.
The method in the previous chapter does not allow for sharing variables.
For example, if you declare a variable within a header file, like this:
I'm getting an error saying 'declaration is redundant' and it won't compile.
sum.h
/* sum.h */
int sum(int min, int max);
int Public;
To better understand this error, you need to understand the meaning of declarations.
So far, we've been using the term declare to describe both functions and variables.
Actually, declarations have two kinds of functionality.
When variables or functions are declared, the compiler memorizes their names and shapes.
This is a feature called the Declaration.
And simultaneously, the compiler actually creates variables and functions.
This is a function called definition.
Previously, we always performed declaration and definition simultaneously with these variables.
Declarations merely inform the compiler about the form of variables and functions.
As long as the form is the same, it doesn't matter how many times you declare it.
However, in terms of the definition, this creates concrete instances of functions and variables.
It results in an error because it becomes difficult to distinguish between multiple instances of the same function or variable.
Prototype declaration, if so.
In the previous chapter, we succeeded by writing only the prototype declaration.
This is because a prototype declaration only declares the method without defining it.
Therefore, you can write as many prototype declarations as you like (using the same syntax).
This is because a prototype declaration only declares the method without defining it.
Therefore, you can write as many prototype declarations as you like (using the same syntax).
External declaration
The preceding section explained that variables cannot be declared multiple times because declaration and definition occur simultaneously.
To resolve this issue, you need to declare things multiple times and define them only once.
In that case, a extern declaration is provided for simply declaring it.
Declaration without definition.
The usage of extern declarations is straightforward.It's just a matter of preceding previous declarations with the keyword 'extern'.
The following header file contains extern declarations for functions and variables.
This extern declaration allows you to share variables between different source files.
First, declare some variables as extern within a header file.
Now the variable Public can be shared across all source files that include sum.h.
However, since it is not defined, the variable Public has not been created.
Therefore, you create an instance by performing a regular declaration within one source file.
With this, the variable Public will be accessible from both main.c and sum.c.
The following program is an example of it in action.
The output of this program is as follows.
To resolve this issue, you need to declare things multiple times and define them only once.
In that case, a extern declaration is provided for simply declaring it.
Keyword
【External declaration】
Declaration without definition.
The usage of extern declarations is straightforward.It's just a matter of preceding previous declarations with the keyword 'extern'.
The following header file contains extern declarations for functions and variables.
External declaration
/* sum.h */
extern int sum(int min, int max);
extern int Public;
This extern declaration allows you to share variables between different source files.
First, declare some variables as extern within a header file.
sum.h
/* sum.h */
extern int sum(int min, int max);
extern int Public; /* Extern declaration of variables */
Now the variable Public can be shared across all source files that include sum.h.
However, since it is not defined, the variable Public has not been created.
Therefore, you create an instance by performing a regular declaration within one source file.
sum.c
/* sum.c */
int Public; /* Creating the Entity of a Variable */
int sum(int min, int max)
{
int num;
num = (min + max) * (max - min + 1) / 2;
return num;
}
With this, the variable Public will be accessible from both main.c and sum.c.
The following program is an example of it in action.
main.c
/* main.c */
#include "sum.h"
#include <stdio.h>
int main(void)
{
int value;
value = sum(50, 100);
printf("%d\n", Public);
return 0;
}
sum.c
/* sum.c */
int Public;
int sum(int min, int max)
{
int num;
num = (min + max) * (max - min + 1) / 2;
Public = 100;
return num;
}
The output of this program is as follows.
Results
100
to a minimum
Sharing variables is a very useful technique, but please avoid overusing it.
The fundamental purpose of splitting code into multiple files is to keep functionality independent.
However, using variable sharing allows the same variables to be used,
which diminishes the meaning of keeping functionality independent.
Therefore, utilize function arguments and return values whenever possible,
and only use variable sharing when absolutely necessary.
The fundamental purpose of splitting code into multiple files is to keep functionality independent.
However, using variable sharing allows the same variables to be used,
which diminishes the meaning of keeping functionality independent.
Therefore, utilize function arguments and return values whenever possible,
and only use variable sharing when absolutely necessary.
Header file inclusion prevention
So far, we have used extern declarations to avoid redundant definitions, but...
Actually, there is a way to prevent header file double inclusion itself.
We will use the #ifndef~#endif conditional directive for that.
The `#ifndef~#endif` pseudo-instructions are used only when a symbol is not defined.
It's a notation indicating the compilation of the program enclosed in between.
This property can be leveraged to create header files such as the following.
In this header file, we first check if the symbol _INCLUDE_SUM_ is defined.
Compile the subsequent program only if it was not previously defined.
Here, using the #define pseudo-instruction within a program that will be compiled later,
Since the symbol _INCLUDE_SUM_ is defined, if this header file is included for the second time,
The symbol _INCLUDE_SUM_ is already defined, and compilation will not proceed.
This way, you won't have to repeat the same declaration multiple times.
It seems like it might only be usable once, as it won't be compiled again afterward.
Ultimately, all source files will be combined, so a single compilation is sufficient.
In general, this is often combined with an extern declaration as follows.
Furthermore, including comments like these will result in a more complete header file.
I recommend always using this writing style, as it minimizes the likelihood of issues.
Actually, there is a way to prevent header file double inclusion itself.
We will use the #ifndef~#endif conditional directive for that.
The `#ifndef~#endif` pseudo-instructions are used only when a symbol is not defined.
It's a notation indicating the compilation of the program enclosed in between.
This property can be leveraged to create header files such as the following.
sum.h
/* sum.h */
#ifndef _INCLUDE_SUM_
#define _INCLUDE_SUM_
int sum(int min, int max);
#endif
In this header file, we first check if the symbol _INCLUDE_SUM_ is defined.
Compile the subsequent program only if it was not previously defined.
Here, using the #define pseudo-instruction within a program that will be compiled later,
Since the symbol _INCLUDE_SUM_ is defined, if this header file is included for the second time,
The symbol _INCLUDE_SUM_ is already defined, and compilation will not proceed.
This way, you won't have to repeat the same declaration multiple times.
It seems like it might only be usable once, as it won't be compiled again afterward.
Ultimately, all source files will be combined, so a single compilation is sufficient.
In general, this is often combined with an extern declaration as follows.
Furthermore, including comments like these will result in a more complete header file.
I recommend always using this writing style, as it minimizes the likelihood of issues.
sum.h
/* sum.h */
#ifndef _INCLUDE_SUM_
#define _INCLUDE_SUM_
/* Function to calculate the sum between min and max
int min minimum value
int max maximum value
Return value int Total value
*/
extern int sum(int min, int max);
#endif
Location of explanatory comments
Programs with comments explaining functions like this are quite common. This way, whether someone else is looking at it or you revisit it later, you can quickly grasp the content, which is convenient.
However, I believe such comments should be written in the header file, not in the source file.
This is because the header file is read by everyone who uses the function,
while the source file is not necessarily read by everyone.
However, I believe such comments should be written in the header file, not in the source file.
This is because the header file is read by everyone who uses the function,
while the source file is not necessarily read by everyone.
It feels like it could be automated, though...
Header files follow a strict format, so it might seem possible to generate them automatically from source files. In fact, many other languages handle this automatically, making header files unnecessary. However, header files also serve as design documents for source files. You create the header file first and then build the program to match it.
Furthermore, source files often contain functions and variables specific to that file, which don't need to be declared in the header.
If auto-generation were to include these unnecessary declarations in the header, it would create a certain kind of waste.
While C requires programmers to be mindful of many things,
it is designed so that by being conscious of these aspects, waste can be significantly reduced.
Furthermore, source files often contain functions and variables specific to that file, which don't need to be declared in the header.
If auto-generation were to include these unnecessary declarations in the header, it would create a certain kind of waste.
While C requires programmers to be mindful of many things,
it is designed so that by being conscious of these aspects, waste can be significantly reduced.
About This Site
Learning C language through suffering (Kushi C) isThis is the definitive introduction to the C language.
It systematically explains the basic functions of the C language.
The quality is equal to or higher than commercially available books.




