Converting false to pointer type void*? - c++

Can someone explain me what is going on here...?
I had this code:
#include <fstream>
#include <string>
#include <iostream>
int main(){
std::ifstream file("test.txt");
std::string x;
while (true) {
if (!(file >> x)) return 0;
std::cout << x << "\n";
}
}
...compiles fine, does what it is supposed to do, no problem so far. Sometimes I dont like the ! so much, because it can be overlooked easily, so I replaced the if with
if ((file >> x)==false) return 0;
..and suddenly my compiler (gcc 4.8.5) complains with a warning:
warning: converting ‘false’ to pointer type ‘void*’ [-Wconversion-null]
if ((file >> x)==false) return 0;
and this is where I am starting to be puzzled. Where is the void* coming from? Doesnt >> return a reference that should be casted to a bool? Why is false converted to void*? Why isnt the same warning triggered when I dont explicitly write false?
Out of curiosity I also tried this:
if ((file>>x)==true) return 0;
which causes a storm of errors starting with
error: no match for ‘operator==’ (operand types are ‘std::basic_istream<char>’ and ‘bool’)
if ((file>>x)==true) return 0;
^
and now I am completely lost. How is false a differnt bool than true? Different values of course, but I always thought true and false are of same type.

Recall that C++ has operator overloads. In particular, std::basic_istream overloads operator!.
Alas, there is no enforcement that operator overloads are semantically consistent, so there is no overload for == between an istream and a bool. Thus the comparison with true fails. However, the compiler is also allowed to apply implicit conversions in order to make an expression compile - in this case false may be implicitly converted to a null pointer, and basic_istream has an overload of operator void* (though apparently that was replaced with operator bool in C++11 - presuambly to fix the inconsistency).

Related

What’s the best way to cast a function pointer from one type to another?

I’ve searched Stack Overflow for an answer, but I get nothing specific to this problem: only general cases about use of various types of cast operators.
So, the case in point is when retrieving a function address with the Windows GetProcAddress() API call, which returns a function pointer of type FARPROC, with: typedef INT_PTR (__stdcall *FARPROC)();.
The trouble is, the actual function sought rarely (if ever) has this actual signature, as shown in the MRCE code, below. In this code, I have shown a variety of different attempts to convert the returned value to a function pointer of the appropriate type, with all but the fourth method commented out:
#include <Windows.h>
#include <iostream>
typedef DPI_AWARENESS_CONTEXT(__stdcall* TYPE_SetDPI)(DPI_AWARENESS_CONTEXT); // Function pointer typedef
static DPI_AWARENESS_CONTEXT __stdcall STUB_SetDpi(DPI_AWARENESS_CONTEXT) { return nullptr; } // Dummy 'stub' function
static DPI_AWARENESS_CONTEXT(__stdcall* REAL_SetDpi)(DPI_AWARENESS_CONTEXT) = STUB_SetDpi; // Func ptr to be assigned
using std::cout; using std::endl;
int main()
{
HINSTANCE hDll = LoadLibrary("User32.dll");
if (!hDll) {
cout << "User32.dll failed to load!\n" << endl;
return 1;
}
cout << "User32.dll loaded succesfully..." << endl;
// (1) Simple assignment doesn't work ...
// REAL_SetDpi = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
// (2) Using 'C'-style cast does work, but it is flagged as 'evil' ...
// REAL_SetDpi = (TYPE_SetDPI)GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
// (3) Using reinterpret_cast: seems OK with clang-cl but MSVC doesn't like it ...
// REAL_SetDpi = reinterpret_cast<TYPE_SetDPI>(GetProcAddress(hDll,
// (4) Using a temporary plain "void *": OK with MSVC but clang-cl complains ...
void* tempPtr = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
REAL_SetDpi = reinterpret_cast<TYPE_SetDPI>(tempPtr);
// (5) Using a union (cheating? - but neither clang-cl nor MSVC give any warning!) ...
// union {
// intptr_t(__stdcall* gotProc)(void);
// TYPE_SetDPI usrProc; // This has the 'signature' for the actual function.
// } TwoProcs;
// TwoProcs.gotProc = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
// REAL_SetDpi = TwoProcs.usrProc;
if (REAL_SetDpi == nullptr) cout << "SetThreadDpiAwarenessContext function not found!" << endl;
else cout << "SetThreadDpiAwarenessContext function loaded OK!" << endl;
FreeLibrary(hDll);
return 0;
}
The various error/warning messages given by the clang-cl and native MSVC compiler, for each of the 5 options are as follows:
// (1) Simple assignment doesn't work ...
REAL_SetDpi = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
clang-cl -> error : assigning to 'DPI_AWARENESS_CONTEXT (*)(DPI_AWARENESS_CONTEXT) __attribute__((stdcall))'
(aka 'DPI_AWARENESS_CONTEXT__ *(*)(DPI_AWARENESS_CONTEXT__ *)') from incompatible type 'FARPROC'
(aka 'long long (*)()'): different number of parameters (1 vs 0)
Visual-C -> error C2440: '=': cannot convert from 'FARPROC' to
'DPI_AWARENESS_CONTEXT (__cdecl *)(DPI_AWARENESS_CONTEXT)'
message : This conversion requires a reinterpret_cast, a C-style cast or function-style cast
This error is (of course) expected, but the one confusing thing to me is why MSVC shows my function as __cdecl when I have explicitly declared it __stdcall?
// (2) Using 'C'-style cast does work, but it is flagged as dangerous ...
REAL_SetDpi = (TYPE_SetDPI)GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
clang-cl -> warning : use of old-style cast [-Wold-style-cast]
Visual-C -> warning C4191: 'type cast': unsafe conversion from 'FARPROC' to 'TYPE_SetDPI'
warning C4191: Calling this function through the result pointer may cause your program to fail
Generally, I endeavour to completely avoid old, ‘C’-style casts in my code! Where I am forced to do cast between ‘unrelated’ objects, I use explicit reinterpret_cast operators, as these are far easier to track down in code if problems arise. So, for case 3:
// (3) Using reinterpret_cast: seems OK with clang-cl but MSVC doesn't like it ...
REAL_SetDpi = reinterpret_cast<TYPE_SetDPI>(GetProcAddress(hDll, "SetThreadDpiAwarenessContext"));
clang-cl -> No error, no warning!
Visual-C -> warning C4191: 'reinterpret_cast': unsafe conversion from 'FARPROC' to 'TYPE_SetDPI'
Calling this function through the result pointer may cause your program to fail
Here, the MSVC warning is pretty much the same as for the C-style cast. Maybe I could live with this, but case 4 makes things more interesting:
// (4) Using a temporary plain "void *": OK with MSVC but clang-cl complains ...
void* tempPtr = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
REAL_SetDpi = reinterpret_cast<TYPE_SetDPI>(tempPtr);
clang-cl -> warning : implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension
[-Wmicrosoft-cast]
warning : cast between pointer-to-function and pointer-to-object is incompatible with C++98
[-Wc++98-compat-pedantic]
Here, MSVC gives no warning – but I feel I’m simply ‘fooling’ the compiler! I can’t see how this can have any different overall effect than the code in case 3.
// (5) Using a union (cheating? - but neither clang-cl nor MSVC give any warning!) ...
union {
intptr_t(__stdcall* gotProc)(void);
TYPE_SetDPI usrProc; // This has the 'signature' for the actual function.
} TwoProcs;
TwoProcs.gotProc = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
REAL_SetDpi = TwoProcs.usrProc;
I did post this as an answer (now retracted), to which #formerlyknownas_463035818 pointed out that this is officially Undefined Behaviour and/or disallowed in C++ (the link given by the aforementioned commentator).
Which option do I currently use?
Well, as my software is specifically Windows-oriented, I use the last (option 4) for two reasons: (1) the clang-cl warning is the ‘least scary’; and (2) I like to think that MSVC is probably the best ‘mediator’ for compiling/building Windows apps.
EDIT: Since first posting this question, and having 'reviewed' the various comments and suggestions made, I have now changed all
instances of this type of cast (that is, from a function pointer
loaded via GetProcAddress) in my code to using the following
conversion 'function', defined in my global header file:
template<typename T> T static inline FprocPointer(intptr_t(__stdcall* inProc)(void)) {
__pragma(warning(suppress:4191)) // Note: no semicolon after this expression!
return reinterpret_cast<T>(inProc);
}
This allows for easy/rapid location of any such casts, should I need (or wish) to change the way they work in future.
Why does it matter?
Maybe it doesn’t! However, elsewhere in my code, I have come across an unexpected crash, when using function pointers loaded via GetProcAddress() - not any standard WinAPI calls, but functions from my own DLLs, loaded as plug-in modules. The code snippet below shows a potential case-in-point:
// --------------------------------------------------------------------------------------------------------------------
// These two routines are the 'interceptors' for plug-in commands; they check active plug-ins for handlers or updaters:
static int plin; //! NOTA BENE: We use this in the two functions below, as the use of a local 'plin' loop index
// is prone to induce stack corruption (?), especially in MSVC 2017 (MFC 14) builds for x86.
void BasicApp::OnUpdatePICmd(uint32_t nID, void *pUI)
{
//! for (int plin = 0; plin < Plugin_Number; ++plin) { // Can cause problems - vide supra
for (plin = 0; plin < Plugin_Number; ++plin) {
BOOL mEbl = FALSE; int mChk = -1;
if ((Plugin_UDCfnc[plin] != nullptr) && Plugin_UDCfnc[plin](nID, &mEbl, &mChk)) {
CommandEnable(pUI, mEbl ? true : false);
if (mChk >= 0) CmdUISetCheck(pUI, mChk);
return;
}
}
CommandEnable(pUI, false);
return;
}
void BasicApp::OnPluginCmd(uint32_t nID)
{
//! for (int plin = 0; plin < Plugin_Number; ++plin) { // Can cause problems - vide supra
for (plin = 0; plin < Plugin_Number; ++plin) {
piHandleFnc Handler = nullptr; void *pParam = nullptr;
if ((Plugin_CHCfnc[plin] != nullptr) && Plugin_CHCfnc[plin](nID, &Handler, &pParam) && (Handler != nullptr)) {
Handler(pParam);
return;
}
}
return;
}
Note that, Plugin_UDCfnc and Plugin_CHCfnc are arrays of function pointers, loaded as described above.
And, finally, what was my question, again?
Two-fold:
Is it ‘safe’ to ignore the warnings?
Is there a better way, using the Standard Library (I’m still getting used to using this)
– maybe something like std::bind()?
Any help, suggestions or recommendations will be greatly appreciated.
EDIT: I use the native MSVC compiler for my “Release” builds (with /Wall), and a few specific warnings explicitly disabled (locally) in code. From time to time, I run my entire code base through the clang-cl compiler, to look for other warnings of possible dodgy code (very useful, actually).
I think C/C++ are lacking a generic function pointer type, like void* as a generic object pointer type.
Generally, converting from one function pointer into another is supported, provided that you don't call the wrong function pointer type. See [expr.reinterpret.cast]/6:
A function pointer can be explicitly converted to a function pointer of a different type.
A warning that is issued when casting one function pointer type to another is generally useful. Having such casting might cause a call to a function with the wrong signature. Such a problem might affect only a certain CPU architecture, or be noticed only with certain OS builds, so it might not be apparent after initial testing. The Standard just says unspecified, see [expr.reinterpret.cast]/6:
Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
Whether void* can be converted to function pointer type and whether it even has enough bits is implementation specific. True for Windows, though. I wouldn't endorse Windows-specific habits for a generic problem. See
[expr.reinterpret.cast]/8:
Converting a function pointer to an object pointer type or vice versa is conditionally-supported.
Type punning with unions raises an issue with strict aliasing (What is the strict aliasing rule?), so not a good way to outsmart a compiler.
So, live with local warning suppression near your GetProcAddress calls, or in a GetProcAddess wrapper. Use reinterpret_cast.
If you're going to use a helper function that casts one function type into another without a warning, be sure to use it only in GetProcAddress-like scenario, when you use some generic signature to temporary store function pointer, but that signature is not an actual signature -- not to call a function pointer by a not intended type.
Sorry.

c++ enum can compare to integer but not assign from integer?

#include <iostream>
enum mode { MODE0=0, MODE1, NUM_MODES};
int main(int args, char ** argv) {
int i = 1;
std::cout << (i == MODE0 ? "true" : "false") << "\n";
std::cout << (i == MODE1 ? "true" : "false") << "\n";
mode test;
test = i; // error
}
Why is it that the comparison of i to enum values works fine, but I get compilation error when assigning mode test variable to an integer value?
enum.cc:10:8: error: invalid conversion from 'int' to 'mode'
[-fpermissive]
My question is specifically about why comparison works and assignment doesn't (not how to fix my code) and it has received a couple of good explanations below.
MODE0, MODE1 and NUM_MODES are guaranteed to be convertible to int (the underlying type of the enum) but the reverse is not true. Not all int can be converted to mode. For example, what is the matching mode for the int 42? Simply put, only the implicit conversion from enum to int is defined, the opposite implicit conversion is not defined.
If you want to convert from int to mode you can preform a static_cast to signal that you are taking the responsibility of ensuring that the value being converted is always legal to convert to mode. Try
test = static_cast<mode>(i);
You can use strongly typed enumerations by adding the class keyword to your enum to prevent any implicit casts and to limit the scope of the enum value names. The definition would look like enum class mode { MODE0 = 0, MODE1, NUM_MODES };. In this case, you must quality the enum value names, for example, you would need to use mode::MODE0 instead of MODE0. This has the advantage that it avoids name collisions.
It's because there is a conversion from an enumerated type to int but there is no conversion in the opposite direction. For the comparison, MODE0 gets promoted to int. For the assignment, i would have to be converted to mode.
Look at it this way. When you do a comparison it doesn't matter if the int is not a valid possible value. If it is not then the comparison will fail and we can go on. Now when we go and try to assign an int to an enum you could assign to it a value that isn't mapped to the enum values. Since we don't want this implicitly happening the conversion is invalid. If you want to tell the compiler that it is okay, you know what you are doing, then you can cast it like:
test = static_cast<mode>(i);

Why is this code on array of structures working?

This code on array of structures is working but according to my understanding it shoudn't.
Code:
#include<stdio.h>
#include<string.h>
int main()
{
struct virus {
char signature[25];
char status[20];
int size;
} v[2] = {
"Yankee Doodle", "Deadly", 1813,
"Dark Avenger", "Killer", 1795
};
for(int i=0;i<=1;i++) {
printf("%s %s\n", &v[i].signature, &v[i].status);
}
return 0;
}
According to me, when we try to access the members of a structure using the address of an instance of the structure, we must use the -> operator rather than the . operator. I know that we do it only in case a pointer,but as far as I know, array is functionally equivalent to a pointer. Please help me where I am going wrong with my concepts. And pardon my silly question, because I am just a beginner.
It should not according to Operator Precedence. [] has higher precedence than ., and . has higher precedence than &. So &v[i].signature is equivalent to & ( (v[i]).signature). So first the ith item is taken from v, then it's signature member is accessed, which is a character array, and then & is applied which gives the address of the character array.
It works in VS, but this is not standard behavior.
It doesn't really work. You probably expected &v[i].signature to be (&v[i]).signature (which should have been (&v[i])->signature), but it's actually &(v[i].signature), of type char (*)[25]. If the program still produces the expected output, then that's purely by chance.
GCC would have told you this even without -Wall:
$ gcc -c a.c
a.c: In function ‘main’:
a.c:18:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[25]’ [-Wformat=]
printf("%s %s\n",&v[i].signature,&v[i].status);
^
a.c:18:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[20]’ [-Wformat=]
It's working because:
&v[i].signature == &v[i] == v->signature
(&v).signature == v->signature
You have taken the address using & and dereferenced using [].

Expansion of types from comparison

I know the following code does not work, and I fully understand why. What I actually do not understand is why not:
int main(int argc, char *argv[]) {
std::cout << (atoi(argv[1]) ? "foo" : 'b') << std::end;
}
Why: Of course, this expression may generate either a string or an integer, and this is the error pointed by the compiler:
error: operands to ?: have different types ‘const char*’ and ‘char’
Why not: Since the operator<< have a bind with both of the types const char* and char, why is it the compiler don't perform a code expansion as in a template -- which, I guess, is what is performed.
For example, if I had:
template <class T>
void a(const T& value) {
std::cout << a << std::endl;
}
I could call either a("foo") and a('b'), and -- I guess -- the compiler would do one expansion of the function with the type name [T = const char*] and another one with [T = char].
This may be a simple matter of what C++ does -- and what it does not --, but I fail to see if there's any corner case that would come up as an error if the expansion was performed.
C++ is a compiled statically-typed language and the type of an expression must be known at compile-time. The expression atoi(argv[1]) ? "foo" : 'b' could be a const char* or char, depending on the value of argv[1], which can't be known at compile-time. It's only when the program is actually executed that this value is known. So when the compiler is attempting to turn this expression into machine code, it can't decide which type to treat the expression as.
To see that it really doesn't have anything to do with the operator<<, just have the expression by itself:
int main(int argc, const char* argv[])
{
atoi(argv[1]) ? "foo" : 'b';
}
Even this won't compile, giving the following error:
error: operands to ?: have different types ‘const char*’ and ‘char’
It has nothing to do with cout or operator <<. The expression
atoi(argv[1]) ? "foo" : 'b'
itself wouldn't compile. The 2nd and 3rd operators that you feed to ?: must be either the same type, or types that are implicitly convertible to one other.
This is what you think you should be asking for:
#include <iostream>
#include <utility>
#include <type_traits>
#include <functional>
template<typename Left, typename Right>
auto tri( bool b, Left&& left, Right&& right )
-> decltype( std::forward<Left>(left)() )
{
if (b)
return std::forward<Left>(left)();
else
return std::forward<Right>(right)();
}
int main(int /*argc*/, char *argv[]) {
tri(
atoi(argv[1]),
[]()->std::ostream&{ return std::cout<<"foo"; },
[]()->std::ostream&{ return std::cout<<'b'; }
) << std::endl;
}
but it isn't what ? does.
C++ could be modified to do what you are asking, but the type cascade would grow boundlessly. Each time you have an expression that could return type A or type B, the calling code would have to be forked, which could cause further forking.
Signatures of functions would have to be expanded to list all of the types it "could" return.
Now, while this may be a worthwhile feature for C++ in the future, it isn't what C++ does now. Each expression in C++ has a single, definite type -- in template code, this occurs when you have instantiated the template.
As an aside, the ability to have poly-type return values in C++ would give you capabilities similar to exception handling, where a function could return a value or an error flag. As the calling code would have to automatically fork whenever you call a poly-type return value function, it would have to handle that error flag (either by returning it as an alternative type, or by handling it locally).

c++ error; how should i interpret its meaning?

This may be a silly thing to ask but I am confused with compilation error while trying to use the safe bool idiom while reading this article. Below is my code and I have indicated the lines where i get errors in main() function.
// is OK case
class BoolVer_OK {
bool m_OK;
public:
BoolVer_OK(bool ok) : m_OK(ok){}
operator bool() { return m_OK; }
};
// Not OK Case
class BoolVer_NotOK {
bool m_notOK;
public:
BoolVer_NotOK(bool ok) : m_notOK(!ok){}
bool operator !() const{ reportexecution; return !m_notOK; }
};
main()
{
BoolVer_OK ok(true);
BoolVer_NotOK notOK(true);
ok<<1; // Line#1 is valid
notOK << 1; // Line#2: error: inavlid operand to binary expression ('BoolVer_notOK' and 'int')
return 0;
}
Why we didn't get error at #Line1 while we get at #Line2. Both results in a boolean value before << operator.
ok supports operator bool, and C++ has this nice functionality called implicit casting and also promotion, and in this case for the binary shift operator <<, the bool is promoted to an int, and this is then shifted by 1.
In the second case, you've not provided that operator, and hence there is nothing to implicitly convert (and promote) to int, and you get the error. Try calling !notOk before the shift, now there is a bool, which will be promoted.
I don't think the compiler would automatically insert a call to operator! and then negate that to get you the bool you want. From what I see in the link you provided, they do their tests with a double negation, !!.
ok<<1; // Line#1 is valid
notOK << 1; // Line#2: error: inavlid operand to binary expression ('BoolVer_notOK' and 'int')
This happens because ok is converted to bool implicitly (overloaded operator), whereas notOK doesn't have that operator.
Test out the following code:
BoolVer_OK ok(true);
BoolVer_NotOK notOK(true);
int z = ok<<1; // is valid
//notOK << 1; // error: inavlid operand to binary expression ('BoolVer_notOK' and 'int')
int x = false << 1;
return 0;
The booleans on the left-side of the shift operator are converted to ints and then shifted.