24

I wanted to inspect the address of my variable

volatile int clock;
cout << &clock;

But it always says that x is at address 1. Am i doing something wrong??

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 2
    *1* need not always represent numerical value -- could be logical as well. – Kris Nov 23 '11 at 08:51
  • Possible duplicate of [Why does std::cout convert volatile pointers to bool?](https://stackoverflow.com/questions/2501737/why-does-stdcout-convert-volatile-pointers-to-bool) – melpomene Feb 25 '19 at 12:25

3 Answers3

21

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;
bdonlan
  • 224,562
  • 31
  • 268
  • 324
  • Yes, there is an automatic conversion. It's just that it's automatically converted to `bool`, not `void *`, as C++ does not have automatic conversion to `void *` for pointers (C does, but C++ requires an explicit cast) – bdonlan Nov 23 '11 at 08:50
  • 3
    @bdonlan: You've got it backwards. Any normal pointer can be implicitly converted to `void*`, it's `void*` to `T*` that requires a cast. – GManNickG Nov 23 '11 at 09:42
  • 1
    This answer is incorrect as it stands. The conversion of `T*` to `void*` is implicit. – James Kanze Nov 23 '11 at 09:58
  • 7
    @bdonlan Sorry, but C++ does have an implicit conversion of `T*` to `void*`. The answer as written is wrong, or at least incomplete; what C++ doesn't support is implicitly casting away `volatile`. – James Kanze Nov 23 '11 at 10:01
  • 1
    @JamesKanze Presumably that's because non-`volatile` pointers to `volatile` objects permit exactly the kind of memory-caching that `volatile` is supposed to prevent? – Kyle Strand Sep 29 '16 at 17:22
  • In C++ C-style casting should be avoided - this should be changed to `const_cast`. – Poeta Kodu Mar 06 '18 at 20:00
17

There's an operator<< for const void*, but there's no operator<< for volatile void*, and the implicit conversion will not remove volatile (it won't remove const either).

As GMan says, the cv-qualification of the type pointed to should be irrelevant to the business of printing an address. Perhaps the overload defined in 27.7.3.6.2 should be operator<<(const volatile void* val);, I can't immediately see any disadvantage. But it isn't.

#include <iostream>

void foo(const void *a) {
    std::cout << "pointer\n";
}

void foo(bool a) {
    std::cout << "bool\n";
}

int main() {
    volatile int x;
    foo(&x);
    std::cout << &x << "\n";
    int y;
    foo(&y);
    std::cout << &y << "\n";
    void foo(volatile void*);
    foo(&x);
}

void foo(volatile void *a) {
    std::cout << "now it's a pointer\n";
}

Output:

bool
1
pointer
0x22cd28
now it's a pointer
Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Beat me by literally one second, urg :(. To add on: in the solution proposed by bdonlan, the c-style cast as a `const_cast`. For the purpose of printing, it's not really a concern. – GManNickG Nov 23 '11 at 09:50
0

This is because there is no overload for operator << that takes a pointer to volatile, and there is no pointer conversion that could satisfy it.

According to C++ standard,

for any type T, pointer to T, pointer to const T, and pointer to volatile T are considered distinct parameter types, as are reference to T, reference to const T, and reference to volatile T.

Operator << has no overload for pointers to non-static member, pointers to volatile, or function pointers, so attempting to output such objects invokes implicit conversion to bool.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523