Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?
There are a few pieces to this that allow all of these combinations of operators to work the same way.
The fundamental reason why all of these work is that a function (like foo
) is implicitly convertible to a pointer to the function. This is why void (*p1_foo)() = foo;
works: foo
is implicitly converted into a pointer to itself and that pointer is assigned to p1_foo
.
The unary &
, when applied to a function, yields a pointer to the function, just like it yields the address of an object when it is applied to an object. For pointers to ordinary functions, it is always redundant because of the implicit function-to-function-pointer conversion. In any case, this is why void (*p3_foo)() = &foo;
works.
The unary *
, when applied to a function pointer, yields the pointed-to function, just like it yields the pointed-to object when it is applied to an ordinary pointer to an object.
These rules can be combined. Consider your second to last example, **foo
:
- First,
foo
is implicitly converted to a pointer to itself and the first*
is applied to that function pointer, yielding the functionfoo
again. - Then, the result is again implicitly converted to a pointer to itself and the second
*
is applied, again yielding the functionfoo
. - It is then implicitly converted to a function pointer again and assigned to the variable.
You can add as many *
s as you like, the result is always the same. The more *
s, the merrier.
We can also consider your fifth example, &*foo
:
- First,
foo
is implicitly converted to a pointer to itself; the unary*
is applied, yieldingfoo
again. - Then, the
&
is applied tofoo
, yielding a pointer tofoo
, which is assigned to the variable.
The &
can only be applied to a function though, not to a function that has been converted to a function pointer (unless, of course, the function pointer is a variable, in which case the result is a pointer-to-a-pointer-to-a-function; for example, you could add to your list void (**pp_foo)() = &p7_foo;
).
This is why &&foo
doesn't work: &foo
is not a function; it is a function pointer that is an rvalue. However, &*&*&*&*&*&*foo
would work, as would &******&foo
, because in both of those expressions the &
is always applied to a function and not to an rvalue function pointer.
Note also that you do not need to use the unary *
to make the call via the function pointer; both (*p1_foo)();
and (p1_foo)();
have the same result, again because of the function-to-function-pointer conversion.
How far should one take e-mail address validation?
There is no 100% reliable way of confirming a valid email address other than sending an email to user and and waiting for a response, like most forums.
I would go with the simple "@" validation rule and then email the user to confirm their email address.
Although, this is my personal opinion... I await other suggestions.
Related Topics
The Definitive C++ Book Guide and List
Why Can Templates Only Be Implemented in the Header File
What Are the Basic Rules and Idioms For Operator Overloading
Undefined Behavior and Sequence Points
What Is the Strict Aliasing Rule
Why Does Std::Getline() Skip Input After a Formatted Extraction
What Are Copy Elision and Return Value Optimization
Why Isn't Sizeof For a Struct Equal to the Sum of Sizeof of Each Member
Iterator Invalidation Rules For C++ Containers
Accessing an Array Out of Bounds Gives No Error, Why
How to Access a Local Variable from a Different Function Using Pointers
Default Constructor With Empty Brackets
When How to Use a Forward Declaration
How to Declare a 2D Array in C++ Using New