No, and why not
To answer your question: no you can't, in the way that you are thinking (i.e. function pointer). What a function pointer is is a variable with an address of another variable. To illustrate, consider how this works when you have a function pointer foo
pointing to function bar
.
int bar() {
}
void baz(int (*foo)()) {
int x = foo(); // Calls the function pointed to bar foo
}
int main() {
int (*foo)();
foo = &bar;
baz(foo); // Cal baz() passing it foo, which points to bar()
}
What foo
holds is the address of bar
. When you pass foo
to some function that expects a function pointer parameter (in this case baz()
), the function dereferences the pointer, i.e. looks at the memory address associated with foo
, gets the address sored in it, in our case the the address of bar
, and then calls a function (in our case, bar
) at that address. To be very careful about this: in the above example baz()
says
- Let me look at the memory associated with
foo
, it has another address in it
- Load that address from memory, and call a function at that address. That function returns an
int
and takes no parameters.
Let's contrast this with a function that calls bar()
directly:
void qux() {
int x = bar(); // Call bar()
}
In this case there is no function pointer. What there is, is an address, supplied by the linker. The linker lays out all the functions in your program, and it knows, for instance that bar()
is at address 0xDEADBEEF
. So in qux()
there is just a jump 0xDEADBEEF
call. In contrast in baz
() there is something like (pseudo-addembly):
pop bar off the stack into register A
read memory address pointed to by register A into register B
jump to memory location pointed to by register B
The way putch()
gets called from printf()
, for instance, is exactly like qux()
calls bar()
, and not like the way baz()
does: putch
gets statically linked into your program, so the address of putch()
is hardcoded in there, simple because fprintf()
doesn't take a function pointer to call for a parameter.
Why #define
is not the answer
#define
is a preprocessor directive, that is, "symbols" defined with #define
are replaced with their values before the compiler even sees your code. This means that #define
makes your program less dynamically modifiable not more. This is desirable in some cases, but in your case it will not help you. To illustrate if you define a symbol like this:
#define Pi 3.14
Then everywhere you use Pi
it is as if you typed 3.14
. Bacause Pi
does not exist, as far as the compiler is concerned, you cannot even take an address of it to make a pointer to it.
Closest you can get to a dynamic putch
Like the others have said, you can have some sort of case statement, conditional, or a global pointer, but the putch
function itself has to be there in the same form.
Global function pointer solution:
void (*myPutch)(char);
putch(char ch) {
myPutch(ch);
}
int main() {
myPutch = putch_Type_A();
...
myPutch = putch_Type_B();
}
If/then/else solution has been provided in other answers
goto solution: This would be an ugly (but fun!) hack, and only possible on von Neumann-type machines, but in these conditions you could have your putch
look like this:
putch(char ch) {
goto PutchTypeB
PutchTypeA:
// Code goes here
return;
PutchTypeB:
// Code goes here
return;
}
You would then overwrite the goto
instruction with goto to some other memory address. You'd have to figure out the opcodes for doing this (from disassembly, probably), and this isn't possible on Harvard architecture machines, so it is out on AVR processors, but it would be fun, if cludgey.