You're calling the function whether or not the pointer to it is NULL.
I follow the example you give, but this statement above doesn't make sense in light of my code or your example. If that were true given the syntax I have in my code, then I would have a gigantic mess of runtime errors all over the place in this codebase and others where attempts to check for function pointer assignment are in fact dereferencing null function pointers and trying to call them. But that is demonstrably not what happens.
These examples from elsewhere online follow my understanding:
In short:
- Using a function pointer without a parameter list gives you the pointer address.
- Using a function pointer with a parameter list executes the function.
If my code were actually calling the function pointer
in the conditional statement, then your code would be doing so twice. In your example (
emphasis mine):
if (fn && (result = fn(paramList)))
{
doThis();
}
Tests the function pointer and if it is not NULL, calls the function and assigns the value returned by the function to the variable "result". If the value of "result" is non-zero, the function "doThis" will be executed.
That's exactly what I'm saying. The condition "fn && (result = fn(paramList))" will first check to make sure the pointer is not null, and then
if it is not null the second half of the logically AND'ed condition will be evaluated (i.e. "fn(paramList)" will run and have its return value stored in the "result" variable).
But I don't want to evaluate the return value inside my
if statement's condition; I want it to be run as a result of the condition. In contrast, my code is equivalent to this mutation of your example:
if (fn)
{
result = fn(paramList);
}
Presumably, this should test the function pointer to ensure it is not null first; then, if it is not null, call the function and store the return value. This is what I am going for. Visually rearranging my code above, it's the same:
if (kg_evt_bluetooth_inquiry_response)
{
skipPacket = kg_evt_bluetooth_inquiry_response(payload + 0, payload + 6, payload[9], payload[10], payload[11], payload[12], name_len ? payload + 13 : 0);
}
Except, I left the braces off because it's one line:
if (kg_evt_bluetooth_inquiry_response)
skipPacket = kg_evt_bluetooth_inquiry_response(payload + 0, payload + 6, payload[9], payload[10], payload[11], payload[12], name_len ? payload + 13 : 0);
Is there anything wrong with this?
I know this should not matter, but have you actually tried to compare to null?
Good question; I have not tried this yet, though it has not been necessary in other places. Using "
if (kg_evt_bluetooth_inquiry_response)" should be logically the same as "
if (kg_evt_bluetooth_inquiry_response != 0)" as far as I know, but it is worth trying just to be sure.
The challenge here, and why I suspect a memory leak or problem somewhere else in my code, is that seemingly irrelevant modifications suddenly cause this to work again (e.g. adding a debug output line). This is why I don't think it's necessarily due to this specific block of code, but at the same time I don't know where to look.
I think it's time for you to post ALL of your code, so that we can try to reproduce the problem.
No problem as far as I'm concerned, but it's a large file in a project with dozens of others, some of which rely on additional hardware outside the Teensy++ 2.0 board (specifically a Bluegiga WT12 module in this particular case). Reproducing the behavior externally may be difficult. The source file in question is here, on Github:
The full project is on the same Github repo:
I'm wondering if you expressly initialised kg_evt_bluetooth_inquiry_response to be null when you declared it. Such as void (*kg_evt_bluetooth_inquiry_response)()=NULL;
I did not, but I can try that as well.
However, the seemingly inexplicable fact remains that the exact same code works with braces around the (non-matching!) conditional code block, and doesn't work when the braces are gone, despite the conditional code being exactly one line.
And, similarly, the same code works (without braces in both cases) when a debug output line is present a dozen lines up, while it locks up without the debug line present.