By the way that I just printed the sizeof a C++ member function pointer on a windows x64 build.
8 was printed on the cmd terminal window.
This is the sizeof of any C pointer in x64 build.
Seems to me that C++ member function pointer is just another C function pointer, so why the conversion is impossible?
|
This is a failure of reasoning in action.
You have not researched what @Duthomhas has written above.
"Seems to me..." is the opening of abandonment of logic in this case. The documentation on the C++ language makes it clear that member function pointers are not just another C function pointer.
The size you happen to get from one compiler is not representative.
I've seen sizes vary greatly for pointer to member functions, as much as triple the size of the platform's atomic pointer. The reason is that the format for this pointer is not specified in the language design, it is left as an implementation detail. This is similar to the format of a floating point number, which is also left to the implementation, and is not the same from one compiler to the next on various platforms, even though if you write on modern Windows machines you'll almost always see the same format.
If C were to make a call into a C++ member function, it would be by fiat (which just happens to be the way C does things sometimes). If a C application were designed to somewhat emulate what is happening, there would be a required structure of data as the first parameter to that function (which C++ treats as an automatic, assumed parameter to the function call, where C does not).
This means, at the root of the problem, is that the analogous signature of a comparable C function to a C++ function differs, and it does so with a type (and data layout) that C is not equipped to understand.
That said, there are machinations one can go through to perform such calls, but it is not a practical act. It may be a curious study, but one that will eventually exhaust all associated time.
When working in various languages to bridge to C++ code, there is a common tactic used. This is typical of Swift to C++ (on Apple). Some "void pointer" is used to represent the instance to a C++ object. These bits mean nothing to the calling language, but this pointer is passed untouched to a C function.
This C function uses the void pointer to cast into a C++ instance pointer, from which a member function call can be made. This is possible because C++ compilers can declare C functions, but still compile with full C++ "awareness". This is a simple but effective model for calling a C++ member function on an instance from a language which has no such ability, using a C function for each member function to be called.
The concept can be generically wrapped into some mechanism for more generalized translation.
Also if MSVC compiler cannot both compile and translate my C++ code to C code then how does MSVC compiler compile and translate my C++ code to assembly code then?
|
First, C was originally purpose built to be an assembler for writing the UNIX operating system. Translating to low level or elemental C is nearly identical in concept to translating into assembler. The low level of C is a kind of assembler, independent of the CPU. That is it's historical origin.
Which is to say, relative to your question, there really isn't a difference between translation from C++ into either target. However, there is no mystery as to why C isn't an option on the MSVC compiler for output - as there isn't an option for the Niagra processor, or the Cray-2 CPU. There simply hasn't been a reason to provide that option. Even if it did, the output to C would not look as you expect. It would be very low level C, and as such, look more like assembler output than C code written by humans.
That said, recall my point that a member function call is merely a call to a function with an assumed parameter of an instance. That isn't a complete definition (I'm not a language lawyer writing the rules), but it is informative as a start. It does leave the impression that one could simply fashion a call (an assembler level call to a function), and pass, at least, that first required pointer to an instance of a C++ object.
As long as the rest of the function itself were then able to continue behaving according to the rules of that object, perhaps that could work, but there are many catches which @Duthomhas eluded, and you should research.
For example, if, in that function, a call to a member function is made that happens to be a virtual function. What is done then? How would C "know" what to do?
In the case of a C++ compiler generating assembler (or C output), it is the C++ compiler that would "know" what to do and fashion the appropriate code to follow the protocols.
Although when I printed the C++ member function pointer itself, 1 was printed on the cmd terminal window on x64 build.
That's strange. Can you explain this to me please?
|
At this point it seems to me you need to develop a new skill not yet demonstrated in your questions.
Research.
The documentation of the C++ language makes it clear that certain details are left to the implementation, and are not standardized. The size of a member function pointer varies from compiler to compiler, even on the same platform.
This is no different that the fact that C++ and C make no specific guarantee of the floating point format, even though on most any compiler in Windows you'll find that is IEEE's 754 format, and I don't recall ever seeing anything else there.
The fact is, it could be any format for floating point representation - which is to say the bits found inside a floating point value may not be what you expect from one platform to another.
This is the same for pointers to members - they are not the same from one compiler to another even on the same platform (though some compilers mirror each other in this aspect).
What you find by a single experiment proves nothing. There are tables available on the internet where that comparison has been done on various compilers to compare the size of the pointer to member function, illustrating not only the variance from one compiler to the next, but in some cases how that size changed in various versions of a particular compiler.
That is the kind of research I suggest you learn to implement, because you're going to be asking questions like these, with repeated versions of "...but I see X, so prove why what I said isn't true..." - without realizing that knowledge is already part of the research, and well known.
We do love to explain things around here, don't get me wrong.
I sense you're at a point of study where you're about to transition upward to a new level, moving fast and thinking hard. This is great.
However, you also demonstrate recognizable habits of thought from that lower level you need to shed in order to soar above that level. Many of us here have been doing this for decades and know the material well. Some responded in this thread. They know exactly what they're talking about. It can be hard to tell the difference between them and others with a few more years than you, but not yet decades of experience and knowledge.
For this, in the anonymous cyberspace, we must re-verify as we study.