What is the default value of a function pointer in C++? (Apparently it can\'t be NULL
, so what is it?)
How is this program supposed to behave and why?
In C++ (and C), pointers (regardless of type) do not have a default value per se; they take what ever happens to be in memory at the time. However, they do have a default initialised value of NULL
.
When you don't explicitly define a constructor, C++ will call the default initialiser on each member variable, which will initialise pointers to 0
. However, if you define a constructor, but do not set the value for a pointer, it does not have a default value. The behaviour is the same for integers, floats and doubles.
Aside
int main()
{
S s = S();
s.f(); // <-- This is calling `f`, not getting the pointer value.
}
In your case the object s
is zero-initialized which means the function pointer is NULL
.
struct S { void (*f)(); };
int main()
{
S s = S();
if ( s.f == NULL)
std::cout << "s.f is NULL" << std::endl;
}
Output:
s.f is NULL
Online demo.
A function pointer can be NULL and you may assign NULL to it. Have a look here for instance:
#include <iostream>
using namespace std;
struct S { void (*f)(); };
int main()
{
S s = S();
s.f = NULL;
return 0;
}
I believe the way you call the constructor of the structure(with ()
), f will be NULL.
First any pointer can be null. It is the one universal truth about pointers. That said, yours will be null, but not necessarily for the reasons you may think;
C++11 § 8.5,p10
An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
This is important because your declaration includes this :
S s = S();
By the definition of value initialization:
C++11 § 8.5,p7
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized.
Which brings us to what it means for your object-type to be zero-initialized:
C++11 § 8.5,p5
To zero-initialize an object or reference of type T means:
if T is a scalar type (3.9), the object is set to the value 0 (zero), taken as an integral constant expression, converted to T (103)
if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized and padding is initialized to zero bits;
if T is a (possibly cv-qualified) union type, the object’s first non-static named data member is zero- initialized and padding is initialized to zero bits;
if T is an array type, each element is zero-initialized;
if T is a reference type, no initialization is performed.
103) As specified in 4.10, converting an integral constant expression whose value is 0 to a pointer type results in a null pointer value.
The latter is the reason you're pointer is null. It will not be guaranteed-so by the standard given the same code, but changing the declaration of s
to this:
S s;
Given a declaration like the above, a different path is taken through the standard:
C++11 § 8.5,p11
If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2.
Which then begs the last question, what is default initialization:
C++11 § 8.5,p6
To default-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
if T is an array type, each element is default-initialized;
otherwise, no initialization is performed.
Function pointer can be NULL, this way you can indicate that they don't point to anything!