7

I have a very simple program which just outputs indefinitely a const pointer pointing to a const volatile char; it goes like this:

const volatile char* const str = "ABCDEFGHIJKL";

while(true) {
    cout << '\r' << str;
}

The problem is that when running this program, the output is 1. There is a way to get around this, which is outputting const_cast<char*>(str) instead of str.

But if I do const_cast<volatile char*>(str) the output is 1, just like before the cast, so I'm guessing the 1 output is caused by the volatile keyword, which is strange because I thought that volatile only makes the compiler avoid optimizations in that variable, which shouldn't change the value of it.

My question, therefore, is how in the world did that 1 came as the output.

NOTE:

I've tried compiling it with GCC in Ubuntu 16.04, and with MinGW in Windows 7, so the compiler is not the problem(I guess).

Garmekain
  • 664
  • 5
  • 18
  • 1
    const and volatile? Does it make sense? –  Jun 28 '17 at 21:25
  • I didn't think so however there is a thread here about that: https://stackoverflow.com/questions/16259939/const-volatile-register-volatile-static-volatile-in-c – drescherjm Jun 28 '17 at 21:26
  • I'm just trying some process memory editing software and came accross this problem. – Garmekain Jun 28 '17 at 21:37
  • 1
    [Interesting](http://coliru.stacked-crooked.com/a/3c72b302c0552fe5) – πάντα ῥεῖ Jun 28 '17 at 21:39
  • `const` and `volatile` on a string literal I've never seen, but I have seen read-only hardware registers declared `const volatile`. – user4581301 Jun 28 '17 at 21:39
  • 1
    @user4581301 -- the const and volatile are **not** on the string literal. They're on the pointer. – Pete Becker Jun 28 '17 at 21:48
  • 1
    @PeteBecker No, it's a const pointer pointing to a const volatile char. – Garmekain Jun 28 '17 at 22:12
  • 1
    @manni66 This replicates a variable which may be altered by other sources, but from the point of view of the program, it has a constant value and address. – Garmekain Jun 28 '17 at 22:14
  • @Garmekain - whoops, that was sloppy of me. But my main point was that the const and volatile are not on the string literal – Pete Becker Jun 28 '17 at 22:30
  • Yup. That's me being lazy. – user4581301 Jun 28 '17 at 22:48
  • By the way, the `const_cast` could be a really bad idea assuming the `volatile` is there for a reason. A safer way would be to manually copy the `const volatile` string into a temporary `char` array (possibly a `std::string`) before outputting it. – Arne Vogel Jun 29 '17 at 09:49
  • @manni66: Assume you have a `struct DeviceDescr` that contains a `char vendorName[16]` and instances of this struct are in device memory, read-only outside of the device, so one might access them through a `const volatile struct DeviceDescr *d`. Now, `d->vendorName`'s type decays to `const volatile char *`. This may be slightly contrived (I'm not an embedded dev), but you get the idea. – Arne Vogel Jun 29 '17 at 09:58

1 Answers1

13

You got nuked by Implicit conversion Sequences (ICS). The C++ std::ostream facilities have no overloads for volatile types. ICS kicks in, and selects the overload for bool type (because pointer types, irrespective of cv qualifications are implicitly convertible to bool).

Hence you see 1... Change your output to std::boolalpha and you should see true instead.

Example:

#include <iostream>
#include <iomanip>

int main(){
    const volatile char* const str = "ABCDEFGHIJKL";
    std::cout << '\r' << str;
    std::cout << '\r' << std::boolalpha << str;
}

Prints:

1
true

Demo

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68