6

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?

struct S { void (*f)(); };

int main()
{
    S s = S();
    s.f();   // What is the value of s.f?
}
21
  • 3
    (Apparently it can't be NULL, ...). Why? Commented Feb 12, 2013 at 9:23
  • 3
    @Mehrdad: Yes, you're wrong. Commented Feb 12, 2013 at 9:25
  • 1
    @Angew: Hmm... any pointer? So you mean even member function pointers can be null? Commented Feb 12, 2013 at 9:32
  • 1
    @Mehrdad maybe it was handling the corner case when the pointer was NULL? i.e. call default handler when pointer points to no function. Commented Feb 12, 2013 at 9:32
  • 2
    @Angew The reason the macro NULL cannot be defined as ((void*)0) is because the C++ standard says it can't. 0 has type int, and except for special wording, couldn't be assigned to any pointer. ((void*)0) has type void*, and except for special wording in the C standard, could not be assigned to a function pointer in C. Both standards contain special language to allow null pointer constants to break the type system. C++ uses the traditional definition; for some reason, the C committee extended the legal types in a null pointer constant. Commented Feb 12, 2013 at 9:46

5 Answers 5

18

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Oh well, 'A' for effort :-)
I was aware of the initialization actually, that's why I did it... but +1 for mentioning it anyway lol.
A whole bunch of Standard quotes just to say "The default value of a function pointer is NULL"?
@Puppy Its not that it can be NULL; its how it got there. It got there by initialization, and the method of initialization is paramount to its final value. If what you said verbatim were universally true, "the default value of a function pointer is NULL", it wouldn't matter. Its not, so it does.
8

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.

1 Comment

@KerrekSB: Yeah, made my life easier choosing between them! xD
3

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.

Comments

3

Function pointer can be NULL, this way you can indicate that they don't point to anything!

Comments

0

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.

Default Initialisation

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.
}

3 Comments

Huh? I thought if I say struct P { void *p; }; P p = P(); then p.p must be NULL, must it not?
@Mehrdad I will try to clarify.
@Alex: S s; and S s = S(); are two *different things! Note that S is POD.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.