4

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();
}
Neha Choudhary
  • 4,840
  • 2
  • 16
  • 22

3 Answers3

11

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.
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • It is happening in the case of header files also. May be it true that static function are invisible. But can you give me any code-example so that I can understand it clearly. becuz I cant find a good answer on google also. – Neha Choudhary Jun 17 '12 at 17:42
  • @NehaChoudhary: Your header files shouldn't list any `static` functions. Please edit your question to include an example of your header file. – Oliver Charlesworth Jun 17 '12 at 17:43
  • @NehaChoudhary: First of all, `static` functions shouldn't be defined in the header file. Secondly, even if they were, it wouldn't work, if you tried using them you'd get an error at link time. – houbysoft Jun 17 '12 at 17:45
  • 2
    @NehaChoudhary: Ok, I've seen your updated question. The problem is that you are defining a function in your header file, which you shouldn't do. Function definitions go in source files. You compile each source file separately, and then combine the results with the linker. If you tell us what tools you're using to compile, we can tell you how to do that. – Oliver Charlesworth Jun 17 '12 at 17:50
  • @houbysoft I am not getting any linker error. I am getting correct answer. And I don't see any difference in static and non static function in c then why they are there in the language? – Neha Choudhary Jun 17 '12 at 17:51
  • @OliCharlesworth I am using turbo C++ compiler with a DOSBOX. :P – Neha Choudhary Jun 17 '12 at 17:52
  • 1
    @NehaChoudhary: Hmm, unfortunately I don't know anything about TCC. I would suggest going through the manual, and finding how to link multiple object files together. – Oliver Charlesworth Jun 17 '12 at 18:08
  • @NehaChoudhary: Strongly reccomend you to move on to a more mainstream and standard adhering compiler like gcc or msvc instead of the age old Turbo C. – Alok Save Jun 17 '12 at 18:13
  • @Als yes I'll do that. Thanks – Neha Choudhary Jun 17 '12 at 18:14
  • @NehaChoudhary: you do not seem to understand the purpose of separate `.c` and `.h` files, and compiling each separately. What you're doing (compiling everything as though it was a single `.c` file) is just not going to work when you move to a more serious project. – houbysoft Jun 17 '12 at 18:47
  • 1
    @NehaChoudhary: (which is why you're not getting the linker error I mentioned. Please read an introductory C tutorial where things like the preprocessor, compiling, and linking are explained.) – houbysoft Jun 17 '12 at 18:50
6

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.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

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:

  1. preprocessing (in which #include directives are replaced with the contents of the included file
  2. compilation (which processes one translation unit at a time)
  3. 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.

Samuel Edwin Ward
  • 6,526
  • 3
  • 34
  • 62