Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does pointer to int convert to void* but pointer to function convert to bool?

Tags:

The C++ Draft Standard (N3337) has the following about conversion of pointers:

4.10 Pointer conversions

2 An rvalue of type “pointer to cv T,” where T is an object type, can be converted to an rvalue of type “pointer to cv void.” The result of converting a “pointer to cv T” to a “pointer to cv void” points to the start of the storage location where the object of type T resides, as if the object is a most derived object (1.8) of type T (that is, not a base class subobject).

and

4.12 Boolean conversions

1 An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true

Based on the above, it is perfectly OK to convert a function pointer or a pointer to an int to a void* as well as bool.

However, given the choice of both, which one should a pointer convert to?

And then, why does a pointer to a function convert to a bool and a pointer to an int convert to a void*?

Program:

#include <iostream> using namespace std;  void foo(const void* ptr) {    std::cout << "In foo(void*)" << std::endl; }  void foo(bool b) {    std::cout << "In foo(bool)" << std::endl; }  void bar() { }  int main() {    int i = 0;    foo(&bar);    foo(&i);    return 0; } 

Output, using g++ 4.7.3:

 In foo(bool) In foo(void*) 
like image 514
R Sahu Avatar asked Aug 28 '14 15:08

R Sahu


People also ask

What happens when you cast a pointer to an int?

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

Can you typecast pointer from void to int?

You're return ing the value of int sum by setting a void * address to it. In this case, the address is not valid. But, if you keep that in mind and get the value of sum by casting a void * to int it will work.

What is special about a pointer that has the value nullptr or 0?

A null pointer has a reserved value that is called a null pointer constant for indicating that the pointer does not point to any valid object or function. You can use null pointers in the following cases: Initialize pointers.


1 Answers

Based on the above, it is perfectly OK to convert a function pointer or a pointer to an int to a void* as well as bool.

The quotation states that a pointer to an object can be converted to cv void *. Functions are not objects, and this disqualifies the conversion to cv void *, leaving only bool.


However, given the choice of both, which one should a pointer convert to?

It should convert to const void * over bool. Why? Well, prepare for a journey that starts in Overload Resolution (§13.3 [over.match]/2). Emphasis mine, of course.

But, once the candidate functions and argument lists have been identified, the selection of the best function is the same in all cases:

— First, a subset of the candidate functions (those that have the proper number of arguments and meet certain other conditions) is selected to form a set of viable functions (13.3.2).

— Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed to match each argument to the corresponding parameter of each viable function.

So what about these implicit conversion sequences?

Let's jump over to §13.3.3.1 [over.best.ics]/3 and see just what an implicit conversion sequence is:

A well-formed implicit conversion sequence is one of the following forms:
— a standard conversion sequence (13.3.3.1.1),
— a user-defined conversion sequence (13.3.3.1.2), or
— an ellipsis conversion sequence (13.3.3.1.3).

We're interested in standard conversions sequences. Let's pop over to Standard Conversion Sequences (§13.3.3.1.1 [over.ics.scs]):

1 Table 12 summarizes the conversions defined in Clause 4 and partitions them into four disjoint categories: Lvalue Transformation, Qualification Adjustment, Promotion, and Conversion. [ Note: These categories are orthogonal with respect to value category, cv-qualification, and data representation: the Lvalue Transformations do not change the cv-qualification or data representation of the type; the Qualification Adjustments do not change the value category or data representation of the type; and the Promotions and Conversions do not change the value category or cv-qualification of the type. — end note ]

2 [ Note: As described in Clause 4, a standard conversion sequence is either the Identity conversion by itself (that is, no conversion) or consists of one to three conversions from the other four categories.

The important part is in /2. A standard conversion sequence is allowed to be a single standard conversion. These standard conversions are listed in Table 12, shown below. Notice that both your Pointer Conversions and Boolean Conversions are in there.

Table of standard conversions and their categories and ranks

From here, we learn something important: Pointer conversions and boolean conversions have the same rank. Remember that as we head to Ranking Implicit Conversion Sequences (§13.3.3.2 [over.ics.rank]).

Looking at /4, we see:

Standard conversion sequences are ordered by their ranks: an Exact Match is a better conversion than a Promotion, which is a better conversion than a Conversion. Two conversion sequences with the same rank are indistinguishable unless one of the following rules applies:

— A conversion that does not convert a pointer, a pointer to member, or std::nullptr_t to bool is better than one that does.

We've found our answer in the form of a very explicit statement. Hooray!

like image 76
chris Avatar answered Nov 08 '22 11:11

chris