Is there a way to explicitly define the address pointed to by a function
pointer without using the address-of operator?
To "define it"? No; but the unary & operator will not define it
either, so I suspect you do not mean "tell the compiler what
address to use for the variable or function", but rather "set
the pointer to point to a hardware-level address".
You can attempt the latter, at great risk (because nothing in the
language guarantees there will be a function there, and indeed,
nothing in the language even guarantees that you can construct the
address with an integer), via casts from some integer type:
Such as:
void (*ptrFunction)(void) = NULL;
void funcA(void); //Address of this function is 0x0040010A
int main(void) {
ptrFunction = &funcA; //this works.
ptrFunction = 0x0040010A; //this doesn't, and I want it to.
return 0;
}
The unary "&" is unnecessary (but harmless): having declared the
function funcA() in advance, you can write just:
void (*p)(void) = funcA;
To turn a variable declaration (like that for "p" or "ptrFunction")
into a cast, simply remove the variable name, and add parentheses:
( void (*)(void) )
You can then ask the compiler to apply this cast to any ordinary
integer; whether the result is even remotely useful is impossible
to say without additional knowledge:
void (*p)(void) = (void (*)(void))0x0040010a;
Typically the "additional knowledge" comes from some external
utility, such as a symbol-table examination program, or looking at
the "map" output of the linker, or some such. The actual value
changes every time you build the program, so by the time you obtain
the number and put it in to your source code, it is no longer valid.
(Clearly, this technique is perilous. It does have certain
specialized applications, however, particularly in embedded systems.
On the other hand, embedded systems linkers typically have directives
to allow you to avoid these shenanigans in the first place: you
just tell the linker "the function zog is already in the ROM at
location 0x76543210" or "please put function zog in the ROM at
location 0x76543210". Then you merely need to keep the ROM-map-files
-- the one that says "put it there" and the other one that says
"it was put there" -- in sync.)
Note that on machines like the IBM AS/400, you need some huge amount
of information (something like 128 bytes) to construct a proper
function-pointer, and there are no sufficiently large integers, so
there is no way to write a single integer that corresponds to such
a pointer. On more-conventional machines, though, an ordinary "int"
or "long" is usually sufficient.