8

Functions and variables declared static have internal linkage and they have file scope and they are not visible to functions in other files.

Suppose that i declare a function like this:-

  static int foo(int i);

in one file named file1.c Can I access this function from other file file2.c through the use pointers.

I am going through a book in which it is written that it can done but I don't know how that is possible.

And these are the exact lines:-

Because it has internal linkage , foo can't be called directly from outside the file in which it's defined.(Declaring foo to be static doesn't completely prevent it from being called in another file; an indirect call via a function pointer is still possible).

chanzerre
  • 2,409
  • 5
  • 20
  • 28
  • 1
    If you want to access the function from other compilation units then why are you making it `static` in the first place? – Jon Sep 06 '13 at 11:45
  • @Jon: you can declare a callback as static (no one else may call the function by its identifier), and send its pointer to a setup function to react on event. You force it to be a callback function, and not callable as a regular one. – Gauthier Sep 06 '13 at 13:14
  • @Gauthier: In that case you don't need to do anything more than simply pass the address to the callee: `takes_callback(foo)` -- I see you suggested that already. The OP is asking (as I and other people who answered see it) for a globally accessible function pointer, which is totally pointless. Of course that doesn't prevent people from answering the literal question for moar rep **... – Jon Sep 06 '13 at 13:38
  • It is totally pointless only if the module owning the static function does never change the value of the pointer. But the owning module could make a complex decision internally, and change e.g. which version of an algorithm to run on call to the pointer (transparently for calling modules). – Gauthier Sep 06 '13 at 18:13
  • `static` has no relation to "scope" whatsoever, be that a function or an object. The reference to "scope" in the question is misleading. *Scope* of an identifier depends on *where* it is declared and is completely independent of any declaration specifiers (like `static`). – AnT stands with Russia Sep 06 '13 at 19:24
  • @Gauthier: Even if calling modules need to get the function pointer on their own initiative, don't you think that access should be provided by a getter function instead of making the result of a complex internal decision easily overwritable by any third party? And even if that were a valid scenario, the question makes it clear that the OP is very far away from it. "A book said it's possible"; unfortunately it didn't say it's meaningless, at least in the form presented below. – Jon Sep 06 '13 at 19:55
  • I agree, interfacing with a getter function is safer. And right about being too advanced for this question. – Gauthier Sep 07 '13 at 08:10
  • @andreyt `static` gives internal linkage to variables that would otherwise be global. Do you mean that scope is not the correct word? – Gauthier Sep 07 '13 at 08:15
  • @Gauthier: *Scope* is certainly not the correct term. In C language the therm *scope* describes the visibility of an identifier inside a translation unit. *Scope* is not applicable to global relationships (between different translation units). Keyword `static` affects *linkage* and *storage duration*. In this case the relevant term is *linkage*. *Scope* has nothing to do with it at all. – AnT stands with Russia Sep 07 '13 at 15:45

5 Answers5

6

Maybe you are looking for this?

// file1.h
extern void (*fptr)(void);

// file1.c
static void foo(void)
{
    printf("Hello world!\n");
}

void (*fptr)(void) = &foo;  //or void (*fptr)(void) = foo;

// file2.c
#include "file1.h"

fptr();

Here, foo is static, but its address is referenced through a non-static global variable. And that's perfectly possible.

chanzerre
  • 2,409
  • 5
  • 20
  • 28
2

The function cannot be called by name in any other file since it's static in a different file, but you can do it using function pointer to it.

extern int (*pf)(int);

You need to assign foo to this pointer and then you can access it.

Dayal rai
  • 6,548
  • 22
  • 29
2

Yet another way to do that, which I think is usable, is to make your static function a callback.

//------------------------------
// file react.c
#include "event.h"

static void react_on_event_A(void)
{
    // do something if event_A occurs.
}

void react_init(void)
{
    event_setup(EVENT_A, react_on_event_A);
}

Here you are setting up the react_on_event_A function as a callback that the event driver can call to, but blocking anyone else from calling the function by its identifier. You are really saying to anyone else to keep off that function.

The event driver may look like this:

//------------------------------
// file event.h
typedef enum {
    EVENT_A,
} event_t;

void event_setup(event_t event, void (*callback)(void));
void event_check_and_run(void);


//------------------------------
// file event.c
static void (*event_A_callback)(void);

void event_setup(event_t event, void (*callback)(void))
{
    if (event == EVENT_A) {
        event_A_callback = callback;
    }
}

// Scheduled periodically, or reacting on interrupt.
void event_check_and_run(void)
{
    if (occured(EVENT_A) && (event_A_callback != NULL)) {
        event_A_callback();
    }
}

The advantage of doing so is that the module react controls which other modules (event in this case) have access to its own static function.

With the other alternatives (making the function static or not, or publishing a pointer in the header file), you give access either to no one or to everybody.

Gauthier
  • 40,309
  • 11
  • 63
  • 97
1

H2CO3 gives you the right answer, another way:

/* a.h */
typedef int (*fptr)(int);

fptr call_foo(void);

/* a.c */
#include "a.h"

static int foo(int i)
{
    return i * 2;
}

fptr call_foo(void)
{
    return foo;
}

/* main.c */
#include <stdio.h>
#include "a.h"

int main(void)
{
    fptr fn = call_foo();

    printf("%d\n", fn(2));
    return 0;
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
1

In short: yes you can access static methods through pointers.

To understand this, it's probably best to understand a little more of what goes on under the hood of the compiler.

For clarity a compiled program is written in machine code. There's extra information in the compiled program for the "program loader" but the program itself is just instructions to be carried out by the processor.

When you call a function "foo()" in C, the C compiler will translate this into a "CALL" processor operation. The CALL operation is followed in code by the address of foo (literally a memory address or "offset"). Notice that because it's a memory address, the name ("foo") is not used. Also notice that the linker doesn't need to know about "foo" for this to work.

When you call a function "bar()" in C and the function is in another compilation unit (another C file) the compiler has a bit of a problem because it doesn't know where in the program (where in memory) the function is to call. That is it doesn't know what address to write after the CALL operation. When this happens it writes the code leaving space for the address, but leaves a note for the linker. The note tells the linker "put the address of bar here". So the linker corrects the written program using the memory address. To allow the linker to do this; the compiler writes a table containing every function name and respective address in code.

So what does static do? This simply tells the compiler not to write the name and address for the function in the table passed to the linker. The function still exists in code as a function but the linker doesn't know where it is. Any code within the same compilation unit will know where the function is. So any function within the same compilation unit can pass the address of the function as a pointer outside the compilation unit.

The c code to use to pass a function pointer is something like this:

file1.h

typedef void (* VoidFunctionPointer)();

extern VoidFunctionPointer somethingInteresting;

bar();

file1.c

#include "a.h"
VoidFunctionPointer somethingInteresting;

static void foo() {
    // do something interesting;
}


void bar() {
    // we know what foo is because we're in the same compilation unit
    somethingInteresting = foo;
}

file2.c

#include "a.h"

int main(int argC, char ** argV) {
        bar();
        // we can call somethingInteresting as if it is a function no matter
        // wether it's declared static in code or not
        // this can be foo, just as long as we don't have to use the name "foo"
        somethingInteresting();
}

In this code file2 in effect runs a static function from file1. The key is that file2 never needs the name of that function thus static has no effect over function pointers.

I can recommend reading Microsoft's description of the PE format (.EXE and .DLL) [here]:

http://msdn.microsoft.com/en-us/library/ms809762.aspx

Philip Couling
  • 13,581
  • 5
  • 53
  • 85
  • 1
    The fact that file2 never needs the name is true, but the powerful thing is that file1 could change which function `somethingInteresting` points to, without the need to tell anyone. – Gauthier Sep 06 '13 at 18:25
  • 1
    @Gauthier yes you are correct, function pointers are not there simply to circumvent the `static` restriction. It is merely a side effect. – Philip Couling Sep 06 '13 at 19:30