为什么std :: cout将volatile指针转换为bool?

时间:2010-03-23 16:30:55

标签: c++ pointers iostream volatile standards-compliance

如果你尝试cout指向volatile类型的指针,即使是你通常希望cout打印字符串的volatile指针,你只需要得到'1'(假设指针不是null我认为)。我假设输出流运算符<<是专门用于volatile指针的模板,但我的问题是,为什么?什么用例激发了这种行为?

示例代码:

#include <iostream>
#include <cstring>

int main()
{
    char x[500];
    std::strcpy(x, "Hello world");

    int y;
    int *z = &y;

    std::cout << x << std::endl;
    std::cout << (char volatile*)x << std::endl;

    std::cout << z << std::endl;
    std::cout << (int volatile*)z << std::endl;

    return 0;
}

输出:

Hello world
1
0x8046b6c
1

4 个答案:

答案 0 :(得分:27)

ostream::operator<<具有以下重载:

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

传入易失性指针时,第二个重载无法应用,因为如果没有显式强制转换,则无法将易失性指针转换为非易失性。但是,任何指针都可以转换为bool,因此选择第一个重载,您看到的结果是1或0.

因此,真正的原因不是代表标准委员会的故意决定,而只是标准没有指定带有易失性指针的重载。

答案 1 :(得分:5)

我认为原因是volatile指针不能隐式转换为void *。这在标准的附录C中,理由是类型安全。

  

更改:仅指向非const和   非易失性对象可能是隐含的   转换为void *理由:这个   提高类型安全性。

因此,不是转换为void *(将以十六进制打印),而是将“默认”转换为bool。

答案 2 :(得分:2)

不是答案

这只是问题和答案的措辞问题。问题出现的原因是无法将指针转换为易失性对象转换为void指针,而不是 volatile指针

差异,这是非常重要的,是内存元素是易失性的。在这个问题中,指针不是易失性的(它可以被缓存,并且在更改时不必刷新到内存),而是指向内存:

int volatile * p = f();
p++;      // this does not affect the perceived state of the c++ memory model
++p;
*p = 5;   // this changes the perceived state

重要的原因是,对于内存的易失性指针,指针本身就是具有特殊处理的指针。

void foo( int * );

int * volatile p = f();  // 1
foo(p);                  // 2
int volatile * q = f();
//foo(q);    // error, cannot convert pointer to volatile to pointer to non-volatile
*q = 5;                  // 3
q = 0;                   // 4

在上面的代码中,标记为1和2的操作使其一直到内存。必须将[1]中的赋值转储到内存中。即使p的值在寄存器中,它也将从[2]的内存中加载。标记为[3]的操作修改q指向的值volatile并且将一直到主内存,而操作[4]仅影响指针,而不是{{1本身并不是c ++内存模型可感知状态的一部分,可以在寄存器中执行(注意编译器可以优化volatile并在寄存器中执行操作,而q无法优化。

答案 3 :(得分:1)

我认为问题不是针对volatile类型的指针的显式重载,而是针对volatile类型的指针的重载LACK。编译器不能从指针中隐式删除volatile限定符,因此它检查可用的重载,选择bool版本的operator&lt;&lt;并将指针转换为bool。