//a.c
#include <stdio.h>
#include "b.c"
void main()
{
int var;
var = increment();
var = increment();
var = increment();
count = count + 3;
var = count;
printf("%d", var);
}
//b.c
static int count;
int increment()
{
++count;
return count;
}
Now as in b.c file I have a variable with name count and is static. Now this variable should not be accessible in a.c directly but in my case I can access and manipulate it. So am I missing something?
OUTPUT
6
#include "b.c" in a.c makes b.c a part of the compilation of a.c; they are compiled as one source file.
To keep identifiers in separate source files separate, you compile them separately, without using #include to include one in the other. The separate compilations produce separate object files (.o files on Unix and Unix-like systems), which you then link together with a link command (which may be included in or performed by the gcc command).
Separating the source files also separates an identifier you do want to share between the two files, the function named increment. So a.c will not know about increment, and the compiler will complain. To deal with this for a single function, you can simply declare the function in a.c with extern int increment();. However, the usual technique for managing this sharing of identifiers is:
Create a file named b.h that declares identifiers to be defined in b.c but shared with other source files.
In b.h, declare increment with extern int increment();.
In any source file that will use identifiers from b.c, include b.h with #include "b.h".
In b.c, also include b.h. This provides a check that the declarations in b.h match the definitions in b.c, because the compiler will see both while compiling b.c and report inconsistencies.
You've included b.c in a.c, so they become a single unit as far as the compiler is concerned. Because of this, you can see the static variable.
If you removed the include line, you wouldn't see either count or increment, although the latter would be implicitly declared because it is a function.
Related
I'm a beginner learning c. I know that use of word "static" makes a c function and variable local to the source file it's declared in. But consider the following...
test.h
static int n = 2;
static void f(){
printf("%d", n);
}
main.c
#include <stdio.h>
#include "test.h"
int main()
{
printf("%d", n);
f();
return 0;
}
My expected result was that an error message will throw up, since the function f and variable n is local to test.h only? Thanks.
But instead, the output was
2
2
EDIT:
If it only works for a compilation unit, what does that mean? And how do I use static the way I intended to?
static makes your function/variable local to the compilation unit, ie the whole set of source code that is read when you compile a single .c file.
#includeing a .h file is a bit like copy/paste-ing the content of this header file in your .c file. Thus, n and f in your example are considered local to your main.c compilation unit.
Example
module.h
#ifndef MODULE_H
#define MODULE_H
int fnct(void);
#endif /* MODULE_H */
module.c
#include "module.h"
static
int
detail(void)
{
return 2;
}
int
fnct(void)
{
return 3+detail();
}
main.c
#include <stdio.h>
#include "module.h"
int
main(void)
{
printf("fnct() gives %d\n", fnct());
/* printf("detail() gives %d\n", detail()); */
/* detail cannot be called because:
. it was not declared
(rejected at compilation, or at least a warning)
. even if it were, it is static to the module.c compilation unit
(rejected at link)
*/
return 0;
}
build (compile each .c then link)
gcc -c module.c
gcc -c main.c
gcc -o prog module.o main.o
You have included test.h in main.c.
Therefore static int n and static void f() will be visible inside main.c also.
When a variable or function is declared at file scope (not inside any other { } brace pair), and they are declared static, they are local to the translation unit they reside in.
Translation unit is a formal term in C and it's slightly different from a file. A translation unit is a single c file and all the h files it includes.
So in your case, the static variable is local to the translation unit consisting of test.h and main.c. You will be able to access it in main.c, but not in foo.c.
Meaning that if you have another .c file including test.h, you'll get two instances of the same variable, with the same name. That in turn can lead to all manner of crazy bugs.
This is one of many reasons why we never define variables inside header files.
(To avoid spaghetti program design, we should not declare variables in headers either, unless they are const qualified.)
I declared a global static function in one file
a.c
static void Func1(void);
void Func2(void);
void Func1(void) {
puts("Func1 Called");
}
void Func2(void) {
puts("Func2 Called");
}
and accessed it in b.c
#include <stdio.h>
#include "a.c"
void main() {
Func1();
Func2();
}
the program complied successfully, but as per provided information this should give error: undefined reference to Func1. What wrong is happening here?
You don't include a source file in another, you compile and link them together.
In you case, by saying #include "a.c", you're essentially putting the whole content of a.c into b.c and then starting the compilation, so the static functions and their calls are present in the same translation unit. Thus, there is no issue for compiler to find the called function.
Instead, if you do something like
gcc a.c b.c -o a.out //try to compile and link together
you'll see the expected error, as in this case, a.c and b.c will be two separate translation units.
You declare in header files and define in .c files. So you must use header files to represent the variables or functions you defined. Instead if you use .c files then it leads to multiple definitions.I think that is why you can access that global function.
As I was going through a huge source code, I came across some files where there is only one function declared in, let's say, "code.h" but in "code.c" there are many functions declared and defined.
What is the exact use of declaring and defining functions in .c files ?
How can we access one of those functions in a source file from other source file ?
It would be helpful if anyone can provide an example. Thanks
Splitting a complex routine in multiple smaller routines might make the code easier to understand and also would allow you to follow the single responsibility principle (What is an example of the Single Responsibility Principle?). By declaring and defining them only in a .c file (and declaring them static), you can hide the internal details from users.
If you, for instance, create a library, then your header could only show the public functions you'd like your users to use.
So only put your functions in a header if you'd like those functions available to anyone who includes the header.
If you'd like to keep a function internal to your .c file, seriously consider adding the static keyword as well: what is the advantage of static function?
---edit---
How can we access one of those functions in a source file from other source file ?
If the function isn't static, you could technically declare it anywhere* you'd like and use it there as well. Though, by the above argument, this would be bad practice.
Example:
a.c
int secret_a(int x)
{
return x+1;
}
main.c
#include <stdio.h>
//access a secret function from a.c
int secret_a(int);
int main()
{
printf("secret_a(3) gives: %d\n", secret_a(3));
return 0;
}
(*) anywhere allowed by the C language
How can we access one of those functions in a source file from other source file ?
That is the whole idea with defining some functions in the header, and some only in the c-file.
The functions defined in the header, can be called by other source files.
The functions only defined in the source file, can be hidden - it is a usual practice to mark functions, only declared in a source file, as static.
That makes their visibility limited to the file-scope (only code inside the same file can 'see' the functions).
The reason why this is done is to split the code into a more cleaner and sorted format so that functions concerning a particular operation can be grouped together in to one file and then called from other file. NOTE: this is not mandatory to do but a good programming practice.
Now there are two ways to do it :
1. including the files
2. Declaring the function as extern and then linking them at linking time.
1.
Including the file is the method that you are probably seeing in your code at hand. Functions are defined in one file and that file is included using #include"filename.[h/c]" and then calling the function as it were declared in the given file.
file_to_include.c
void my_func()
{
printf("Hello!\n");
}
file_that_include.c
#include<stdio.h>
#include"file_to_include.c"
int main()
{
my_func();
return 0;
}
to compile you just do
gcc file_that_include.c
using extern you can do the same but with out using the #include directive
file_to_include.c
void my_func()
{
printf("Hello!\n");
}
file_that_include.c
#include<stdio.h>
extern void my_func();
int main()
{
my_func();
return 0;
}
In this case while compiling you need to provide both files to the compiler
gcc file_that_include.c file_to_include.c
I would suggest reading up on the "extern" keyword.
From what I can understand in your question you have two files - "code.h" and "code.c". However, "code.h" only declares certain functions in "code.c":
code.h
int func1();
int func2();
code.c
int func1()
{
return 1;
}
int func2()
{
return 2;
}
int func3()
{
return 3;
}
main.c
#include "stdio.h"
#include "code.h"
extern int func3();
int main()
{
printf("%d ", func1());
printf("%d ", func2());
printf("%d ", func3());
}
Compiling using gcc:
gcc main.c code.c
yields:
main.c: In function ‘main’:
main.c:10:17: warning: implicit declaration of function ‘func3’ [-Wimplicit-function-declaration]
printf("%d ", func3());
and when executed:
1 2 3
The "extern" keyword basically tells the compiler "there is a definition for a function with this declaration" for compiling. During linking the linker will find the definition, and link to it.
This is however a clumsy way of doing it, since the caller ("main.c") needs to know what is going on in "code.c", and continually add more extern declaration, etc. etc.
So rather include functions you which to have global scope in "code.h". If there are functions in "code.c" which od not have global scope, consider making them "static".
Some more reading:
Effects of the extern keyword on C functions
There are two C modules: A and B. They are indepentent from each other.
What is the best way to interchange data between them, if I want to keep them as much independent as possible?
I'll indicate you how to manage an integer, that is very simple! ... :)
An example may be the following. We have three files: a.c, b.c and b.h
The file a.c will manage an integer that is globally and statically allocated (statically to hide the variable to other C modules) by the b.c module that exposes the functions to manage that integer.
The file b.h contains the declaration of the functions the module b.c exposes.
The file a.c is:
#include "b.h"
int main(void)
{
setdata(8);
printf("%d\n",getdata());
return 0;
}
The file b.c may be:
#include "b.h"
static int data; /* Here static means data is hidden to other C modules */
int getdata(void)
{
return data;
}
void setdata(int val)
{
data=val;
}
The file b.h
#ifndef B_H__
#define B_H__
void setdata(int);
int getdata(void);
#endif
In C, you implement information hiding by declaring your persistent variables at "static". Outside a function, this means "only visible from this .c file"; inside a function, it means "local to this function, but persistent".
You then communicate between modules only by calling functions, passing values into them and getting return values from them.
i have a problem. i wrote this code, a.h. a.c and the main.c:
file: a.h
#ifndef _a_H
#define _a_H
int poly (int a, int b, int c, int x);
int square (int x)
{
return x*x;
}
#endif // _a_H
file: a.c
#include "a.h"
int poly (int a, int b, int c, int x)
{
return a*square(x) + b * x +c;
}
file: main.c
#include <stdio.h>
#include "a.h"
int main()
{
int p1 = poly1 (1 ,2 , 1, 5);
int p2 = poly2 (1 ,1 , 3, 5);
printf ("p1 = %d, p2 = %d\n", p1, p2);
return 0;
}
and i got an error:
/tmp/ccKKrQ7u.o: In function 'square':
main.c:(.text+0x0): multiple definition of 'square'
/tmp/ccwJoxlY.o:a.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
so i moved the implementation of the function square to the a.c file and it works.
does any one know why?
thanx
Generally speaking, *.c files are compiled into *.o files, and *.o files are linked to build the executable. *.h files aren't compiled, they are included textually in the *.c files, at the point they are #included.
So by #including "a.h" twice, in two separate *.c files, you've placed your definition for square() into two separate files. When these are compiled, you end up with two copies of square(), one in each *.o file. Then when you link them, the linker sees the two files, and generates an error.
How to avoid this? You've already discovered this. Don't put function definitions in *.h files. Put them in *.c files, and only put the function declarations in the *.h files.
Don't put code in your header files. Both of your .c files include a.h, so both of them get an implementation of square, so your linker complains.
When square() was in the header, it was included in both a.c and main.c, so each of the corresponding object files had its own square(), but without the static modifier, they had the exact same name. Moving it to a.c means that it's only defined once.
If you really want the function in the header file, you can define it with static inline thus:
static inline int square (int x)
{
return x*x;
}
Static will mean that each .c file that includes the .h will have its own version of square(), inline means that the code will be dropped inline, and no function call will actually happen, which is probably what you want here
This happens because your C compiler builds each .c file into an object (.o) file, and then links the object files to make the executable. The contents of a .c file and all the files it includes are known as a compilation unit.
Your example has two compilation units:
main.c, including stdio.h and a.h → compiles to main.o
a.c, including a.h → compiles to a.o
The linker (ld) then attempts to link the .o files but finds they both define square(), because it was in the shared a.h — hence the error. This is why, as some have already pointed out, you should not put function definitions in headers.
If you have the nm utility installed (which you should have), you can run
$ nm main.o
$ nm a.o
in the shell to see that square exists in both files.
(Edit: The term I was thinking of was actually translation unit, but on searching around they seem to mean pretty much the same thing.)
You can't write an implementation (function body) in a header file, otherwise the linker will find more than one reference to that function.
As a rule, put only declarations in header files, not definitions.
You've answered your own question: you've defined square twice, once in each compiled file that includes a.h.
To avoid this you can make square a static function
static int square (int x)
{
return x*x;
}
and add whichever inline hint your compiler uses, e.g. inline or __inline too.