代码之家  ›  专栏  ›  技术社区  ›  Joseph Garvin

为什么std::不能将易失性指针转换为bool?

  •  16
  • Joseph Garvin  · 技术社区  · 14 年前

    如果你试图创建一个指向volatile类型的指针,甚至是一个volatile char指针,在通常情况下你会期望cout打印字符串,那么你只需要得到“1”(我认为指针不是空的)。我假设输出流操作符<<是针对易失性指针的模板,但我的问题是,为什么?什么用例会激发这种行为?

    示例代码:

    #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 回复  |  直到 14 年前
        1
  •  27
  •   interjay    14 年前

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

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

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

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

        2
  •  5
  •   anon    14 年前

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

    更改:仅指向非常量和的指针 非易失性对象可以是隐式的 转化为无效*理由:这 提高类型安全性。

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

        3
  •  2
  •   David Rodríguez - dribeas    14 年前

    不是答案

    这只是问题的措辞和答案的问题。问题是由于无法转换 指向易失性的指针 对象转换为空指针,而不是 易变指针 .

    区别,这是相当重要的,是什么记忆元件是一个挥发性的。在问题中,指针不是易失的(它可以被缓存,并且在更改时不必刷新到内存中),而是指向的内存:

    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]只影响指针,而指针不是 不稳定的 它本身并不是C++内存模型可感知状态的一部分,可以在寄存器中执行(注意编译器可以优化离开)。 Q 并在寄存器中执行操作,同时 无法优化。

        4
  •  1
  •   Mark B    14 年前

    我认为问题不是指向易失性类型的指针的显式重载,而是缺少指向易失性类型的指针的重载。编译器无法从指针中隐式删除volatile限定符,因此它检查可用的重载,选择运算符<<的bool版本,并将指针转换为volatile到bool。