Why Does Std::Cout Convert Volatile Pointers to Bool

Why does std::cout convert volatile pointers to bool?

ostream::operator<< has the following overloads, among others:

ostream& operator<< (bool val );
ostream& operator<< (const void* val );

When you pass in a volatile pointer, the second overload can't apply because volatile pointers cannot be converted to non-volatile without an explicit cast. However, any pointer can be converted to bool, so the first overload is chosen, and the result you see is 1 or 0.

So the real reason for this is not an intentional decision on behalf of the standards committe, but simply that the standard does not specify an overload that takes a volatile pointer.

Why does ostream prints `1` for a string defined as `volatile char[]`?

The only suitable overload of operator<< is that for bool, so the array is converted (via a pointer) to bool, giving true since its address is non-null. This outputs as 1 unless you use the std::boolalpha manipulator.

It can't use the overload for const char * which would output the string, or that for const void * which would output the pointer value, since those conversions would require removing the volatile qualifier. Implicit pointer conversions can add qualifiers, but can't remove them.

To output the string, you'd have to cast away the qualifier:

std::cout << const_cast<const char*>(test) << "\n";

but beware that this gives undefined behaviour since the array will be accessed as if it were not volatile.

printf is an old-school variadic function, giving no type safety. The %s specifier makes it interpret the argument as const char *, whatever it actually is.

Why is the address of this volatile variable always at 1?

iostreams will cast most pointers to void * for display - but no conversion exists for volatile pointers. As such C++ falls back to the implicit cast to bool. Cast to void* explicitly if you want to print the address:

std::cout << (void*)&clock;

How does std::cout work with char pointers?

This happens because the compiler checks the type of the argument and calls the overloaded version of the operator that receives that type.

In the C language, strings are implemented as char arrays terminated with the ’\0’ (nul) character, and arrays are referred to using pointers. So, when the argument received is c, the overloaded operator that receives a char* prints the content of the array up to the nul terminator.

When the argument received is *c, this dereferences the pointer to access its data, and since this is a pointer to char, the overloaded operator that receives a char prints it as a single char.

To print the address of the string array, you can cast the char* pointer to void*, like follows:

std::cout << (void*) c << std::endl;

Am I actually storing the object in the cpu register here?

My thought: Here you might be trying to deny the optimization of compiler for the pointer object ao by using the volatile keyword, Am I right? But this is the only reason why you got '1'! The C++ standard says, even if you specify an object or variable as register it will internally consider only as an auto. For the detaild info about the out put 1 see this link

Address of volatile data member in C++

  1. There is no overload for operator<<(volatile int*) in std::ostream, so implicit type conversions are considered. volatile pointers aren't implicitly convertible to non-volatile, so std::ostream::operator<<(void*) - which would typically be used in case of pointers - is not an option. There is however, an overload for a type that even a volatile pointer can be converted to: operator<<(bool). Since the pointer is not null, it's converted value is true, which cout outputs as 1. If you want to print the address, then const_cast the volatile qualifier away so that the implicit conversion to void* is used. If you want to print the pointed value, then pass the pointed value instead of the pointer by dereferencing it.

    Borland appears to provide a non-standard overload that dereferences the pointer.

  2. There is no way to declare a variable as a register in C++. Yes, there is a register keyword, but it does not change the meaning of the program and has been deprecated (and is planned to be removed in c++17 version of the standard). It's entirely up to the compiler to decide if a variable is stored in memory or merely in a register.

Why can std::cout print the value of nullptr only if returned by a function?

Here is the meaning of nullptr from the CPP Standards [4.10]

  • A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion.

Something the CPP Standards specifies, is that it isn't a std::nullptr_t value, it evaluates to zero or a prvalue of type std::nullptr_t.

In your case, it's pretty much is an (TYPE) pointer to some extent, so when you try to paste it out, it pastes out it's type's value (Where it points to, but by itself it won't). Your function returns an int*, and you give it a nullptr. So what you are basically doing is giving an int* a value. nullptr by itself won't have a value but

int* abc = nullptr;

will.

Why does cout &r give different output than cout (void*)&r?

A char * is a special thing in C++, inherited from C. It is, in most circumstances, a C-style string. It is supposed to point to an array of chars, terminated with a 0 (a NUL character, '\0').

So it tries to print this, following on in to the memory after the 'm', looking for a terminating '\0'. This makes it print some random garbage. This is known as Undefined Behaviour.



Related Topics



Leave a reply



Submit