Linkage and static function confusion - c

I read that
A function with internal linkage is only visible to one compilation
unit. (...) A function declared static has internal linkage
For .c files it sorta makes sense, but I was wondering what happens with static functions in headers, which get included by multiple .c files but usually have an include guard.
I was reading this answer about static functions in headers, and the first item mentions that it doesn't create a symbol with external linkage and the second item mentions the function is available purely through the header file. Isn't that contradictory? How can the function be available and at the same time have no external symbol? So I did a little test:
/* 1.h */
#ifndef ONE_H
#define ONE_H
#include <stdio.h>
static void foo() {
printf("foo from 1.h %p\n", foo);
return;
}
void bar();
#endif
/* 1.c */
#include "1.h"
#include <stdio.h>
void bar() {
printf("foo,bar from 1.c %p,%p\n", foo, bar);
foo();
}
/* 2.c */
#include "1.h"
#include <stdio.h>
int main() {
printf("foo,bar from main %p,%p\n", foo, bar);
foo();
bar();
return 0;
}
...
debian#pc:~ gcc 2.c 1.c
debian#pc:~ ./a.out
foo,bar from main 0x400506,0x400574
foo from 1.h 0x400506
foo,bar from 1.c 0x400559,0x400574
foo from 1.h 0x400559
As expected bar is the same across all files, but shouldn't foo be too? Isn't 1.h included only once? Adding inline to foo resulted in the same behavior. I'm kinda lost.

Read here, how a header file basically works. That should clarify about your actual question.
Briefly: A header file is just inserted instead of the corresponding #include directive. So any declarations or definitions are treated by the compiler as if you actually copy/pasted the text into your file.
Anyway, you should be careful with function definitions in a header. This is deemed bad style in general. It blows the code for instance, creating redundant copies of that function. Also Function pointers cannot be compared (you never know ...). It is often better to bundle the functions into a library with just the declarations in a header (non-static then: external linkage). There are good justifications sometimes, however (no rule without exceptions). One of them are inline functions.

-static functions are functions that are only visible to other functions in the same file (more precisely the same translation unit).
Check this article for a detailed explanation on linkage: http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html

Related

Use of modifier static in c

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.)

Global static function still working in another file

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.

What happens when including header with static declarations?

For example, let's say I have 2 header files.
a.h
#include <stdio.h>
static __inline foo()
{
// do something
}
Then a.h file gets included into b.h:
b.h
#include "a.h"
void bar();
With corresponding b.cpp file:
b.c
#include "b.h"
void bar()
{
foo();
}
main.c
#include "b.h"
void main()
{
bar();
}
Is foo() going to be inlined in b.c file?
Is foo() (static) going to be visible in main.c file since it's included via b.h file or it will be just visible to b.c? (Would guess that it won't be visible since they are not in same translation unit).
foo() is visible in both b and main. The compiler sees the files after the preprocessor has done its job.
main.c after the preprocessor step:
<all the stuff from stdio.h>
static __inline foo()
{
// do something
}
void bar();
void main()
{
bar();
}
One way to remove foo() from main.c is to move inclusion of a.h from b.h to b.c:
Modified b.h:
void bar();
Modified b.c:
#include "a.h"
#include "b.h"
void bar()
{
foo();
}
Is foo() going to be inlined in b.c file?
It is better to say "inlined" into function bar(). Probably it is, but not guaranteed. It is a compiler's decision to inline function or not. Marking function as inline is often just a hint, that may be ignored. Refer to your compiler docs to clarify actual behavior.
Is foo() (static) going to be visible in main.c file since it's
included via b.h file or it will be just visible to b.c? (Would guess
that it won't be visible since they are not in same translation unit).
foo() is visible in every translation unit that includes a.h directly or indirectly. Assuming inlining was ommited, there is another interesting point: each translation unit defines its own copy of foo() i.e. machine code for foo() will be generated for each compiled source. It may be wasteful for non-trivial functions since it leads to bloating of generated code. As consequence you should define static functions in headers only if they are small and are intended to be inlined.

Definition of a function in a C program [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
In a C program, where do you define a function?
Why?
I suppose that the function definition is generally written outside the main function and after the function declaration. It's correct? Why?
Thank you all!
You have to define a function outside main(), because main() is a function itself and nested functions are not supported in C.
Declaring a function is in modern C not necessary, because a function definition implies a function declaration. There are still two reasons to do it:
A function declaration can be exported in a header file and then used by other translation units that import the header file.
C is usually translated one-pass that means that you cannot use a function before it is declared without warning. If you have a function a() calling a function b()and vice versa, you cannot define both functions before declaring at least one.
The only real requirement is that a function be declared before it is first called in a statement, and that it be defined somewhere before everything is linked together (either in another source file that gets translated, or in a previously translated object file or library).
If your program is small and you have everything in a single source file, my recommended practice is to define the function before it is used, like so:
void foo( void )
{
// body of foo
}
void bar( void )
{
...
foo();
...
}
int main( void )
{
...
bar();
...
}
The function definition also serves as a declaration (specifying the return type as well as the number and types of parameters to the function). You could put the definitions after main, but you will still need to declare them before they're called:
int main( void )
{
void bar( void );
...
bar();
...
}
void bar( void )
{
void foo( void );
...
foo();
...
}
void foo ( void )
{
// body of foo
}
You don't have to declare foo within the body of bar, or bar within the body of main; you could declare them both before `main:
void foo( void );
void bar( void );
int main( void )
{
...
bar();
...
}
void bar( void )
{
...
foo();
...
}
The only problem with this style is that if you change the return type of the function or change any of the parameters, you have to chase down any declarations and change them as well. The first way (defining before use) reads "backwards", but it's less of a maintenance headache.
If your program is divided up among multiple source files, the usual practice is to create a separate header file for each source file, and #include that header in any other source file that uses those functions, like so:
/**
* foo.h - Header file for function foo
*/
#ifndef FOO_H // Include guards; prevents the file from being processed
#define FOO_H // more than once within the same translation unit
void foo( void ); // declaration of foo
#endif
/**
* foo.c - Source file for function foo
*/
#include "foo.h"
...
void foo( void ) // definition of foo
{
// body of foo
}
/**
* bar.h - Header file for bar.h
*/
#ifndef BAR_H
#define BAR_H
void bar( void ); // declaration of bar
#endif
/**
* bar.c - Source file for bar.h
*/
#include "foo.h" // necessary because bar calls foo
void bar( void )
{
...
foo();
}
/**
* main.c - Source file for main
*/
#include "bar.h" // necessary because main includes bar
int main( void )
{
...
bar();
}
Note that the header files only contain the declarations of foo and bar, not their actual code. In order for this to work, both foo.c and bar.c must be compiled along with main.c, and the resulting object files must all be linked together. You could do them all at once, like:
gcc -o blah main.c foo.c bar.c
Or you could compile each separately and link the object files together:
gcc -c foo.c
gcc -c bar.c
gcc -c main.c
gcc -o blan main.o foo.o bar.o
Or you could build a library out of foo.c and bar.c and link against that (useful if you want to use foo and bar in other programs):
gcc -c foo.c
gcc -c bar.c
ar cr libblurga.a foo.o bar.o
gcc -o blah main.c -lblurga
Standard C does not support nested functions (that is, defining a function within the body of another function). Some implementations such as gcc support nested functions as an extension, but it's not the usual practice.
Good question. Languages in the Pascal family usually do have the concept of scoped functions, like any other declaration/definition.
I think the answer lies in the origins of C as, heaven forgive me, a better macro assembler of sorts (with a standard library). Functions are mere jump addresses with a little stack magic for parameter and return value handling; function "scope" is just too abstract a concept in that world.
That said, a similar effect can be achieved by grouping "helper functions" together with a globally visible function which needs them in the same file; the helper functions would be declared static and could then only be used in that source file. The net effect is quite similar to scoped functions.
Private declaration goes on top of your .c file:
static int your_function();
Private declaration can be emitted if it is defined above where you are attempting to call it, although for maintainability it's always better to declare your private interface, just like your public, in one place.
Public declaration in your .h file:
extern int your_function();
Keyword 'extern' in header files is always implicitly added to your function declaration, although I tend to attach it explicitly for clarity.
Function definition works for both private and public declarations:
int your_function() {
return 5;
}
Or for private only:
static int your_function() {
return 5;
}
If you mark extern function definition as static, GCC will fail with the following:
error: static declaration of ‘your_function’ follows non-static declaration
When compiler builds your code, it pretty much replaces all your #include statements with the content of the file you are including and the parsing goes from top to bottom as one large file. Once you understand that, most of these things simply start to make sense.

Are static functions in C language really invisible?

I was told that a function defined as static in one .c file is not accessible from other files. But in the following program, I can access the static void show() function from another file. Is my understanding of static functions in C wrong?
a.h (first file):
static void show()
{
printf("I am in static show function in a.c");
}
b.c (another file):
#include"a.h"
void main()
{
show();
}
Remember that #includes work by copy-and-pasting the content of the included file. So in your example, after the #include has been processed, you get this:
static void show()
{
printf("I am in static show function in a.c");
}
void main()
{
show();
}
So clearly main can see show.1
The solution is to not #include .c files. In general, you should only #include header (.h) files. Your static functions shouldn't be declared or defined in the header file, so main will not be able to see it.
1. However, you now actually have two definitions of the show function, one in a.c and one in b.c. For static functions, this isn't a problem, but for non-static functions you would get a linker error.
static keyword changes the linkage specification to Internal Linkage.
A function marked as static will only be visible in that Translation Unit(TU).
Perhaps, You have same named symbols available in that particular TU, where you access the function. The how part of it can be only answered after you show us the code.
EDIT:
When you define a static function in header file, A copy of the same function gets created in every Translation Unit where you include it.Each instance of such a function is treated as a separate function(address of each function is different) and each instance of these functions have their own copies of static local variables & string literals.
Clearly, this will work but this might as well increase the size of your generated binary.
The other answers are correct, but it's not quite accurate to say that the static function is not accessible from another file. It is possible to access the function through a function pointer. It would be more accurate to say that the name of the function is not accessible in another translation unit.
Remember that converting C source code to an executable program consists of conceptual stages, including:
preprocessing (in which #include directives are replaced with the contents of the included file
compilation (which processes one translation unit at a time)
linking (in which the translation units are put together into the final program)
Suppose we have three files. foo.h:
typedef void (*void_function_p)(void);
extern void_function_p foo(void);
foo.c:
#include "foo.h"
#include <stdio.h>
static void baz(void) {
printf("worked!\n");
}
void_function_p foo(void) {
return baz;
}
bar.c:
#include "foo.h"
#include <stdio.h>
int main(void) {
(*foo())();
return 0;
}
This program compiles and prints "worked!" when it runs.
There are two translation units here. One is the code in the preprocessed foo.c (which, because of how #include works also includes the code in foo.h and stdio.h). The other is the code in the preprocessed bar.c (which, again, has its own copy of the code in foo.h and stdio.h).
By having the function foo return a pointer to the static function baz, we are able to call baz from the main function.
Now, consider what happens if we modify main to look like this:
int main(void) {
(*foo())();
baz();
return 0;
}
This code will result in a linker error because the name baz in this translation unit cannot be linked to the definition of baz in the other translation unit.
This is the first advantage of static functions: another programmer cannot accidentally access our baz function from another translation unit.
Now, consider what happens if we modify bar.c to look like this:
#include "foo.h"
#include <stdio.h>
static void baz(void) {
printf("still works!");
}
int main() {
(*foo())();
baz();
return 0;
}
This code will compile, and print "worked!" followed by "still works!"
This is the second advantage of static functions: we've defined two functions (in different translation units) with the same name.
If you try to put both static definitions in the same translation unit, you will get a compiler error about defining baz twice.
As a final note, if you take the program as it now stands and remove all the statics, it will result in a linker error because baz has been defined twice (with external linkage), which is not permitted.

Resources