为啥这个 volatile 变量的地址总是为 1?

Posted

技术标签:

【中文标题】为啥这个 volatile 变量的地址总是为 1?【英文标题】:Why is the address of this volatile variable always at 1?为什么这个 volatile 变量的地址总是为 1? 【发布时间】:2012-01-04 13:44:04 【问题描述】:

我想检查我的变量的地址

volatile int clock;
cout << &clock;

但它总是说 x 在地址 1。我做错了什么吗??

【问题讨论】:

1 不必总是代表数值——也可以是合乎逻辑的。 Why does std::cout convert volatile pointers to bool?的可能重复 【参考方案1】:

iostreams 会将大多数指针转换为 void * 以供显示 - 但 volatile 指针不存在转换。因此,C++ 回退到隐式转换为bool。如果要打印地址,请显式转换为void*

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

【讨论】:

是的,有一个自动转换。只是它会自动转换为bool,而不是void *,因为C++ 没有针对指针自动转换为void *(C 有,但C++ 需要显式转换) @bdonlan:你搞错了。任何普通指针都可以隐式转换为void*,它是void*T*,需要强制转换。 这个答案是不正确的。 T*void* 的转换是隐式的。 @bdonlan 抱歉,C++ 确实有将T* 隐式转换为void*。所写的答案是错误的,或者至少是不完整的; C++ 不支持的是隐式抛弃volatile @JamesKanze 大概是因为非volatile 指向volatile 对象的指针完全允许volatile 应该阻止的那种内存缓存?【参考方案2】:

const void* 有一个operator&lt;&lt;,但volatile void* 没有operator&lt;&lt;,隐式转换不会删除volatile(它也不会删除const)。

正如 GMan 所说,指向的类型的 cv 限定应该与打印地址的业务无关。也许 27.7.3.6.2 中定义的重载应该是operator&lt;&lt;(const volatile void* val);,我看不出有什么缺点。但事实并非如此。

#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";

输出:

bool
1
pointer
0x22cd28
now it's a pointer

【讨论】:

比我快一秒,求 :(。补充一下:在 bdonlan 提出的解决方案中,c 样式转换为 const_cast。出于打印的目的,它并不是真的担心。【参考方案3】:

这是因为operator &lt;&lt; 没有重载,它接受指向volatile 的指针,并且没有指针转换可以满足它。

根据 C++ 标准,

对于任何类型T、指向T、指向const T 和指向volatile T 的指针都被视为不同的参数类型,对T 的引用、对const T 的引用和引用到volatile T

Operator &lt;&lt; has no overload for pointers to non-static member,指向 volatile 的指针或函数指针,因此尝试输出此类对象会调用到 bool 的隐式转换。

【讨论】:

以上是关于为啥这个 volatile 变量的地址总是为 1?的主要内容,如果未能解决你的问题,请参考以下文章

volatile为啥不能保证原子性

为啥将 volatile 与同步块一起使用?

fail-fast机制

Java内存模型-volatile的内存语义

C语言中的关键字volatile

为啥 ostream 为定义为 `volatile char[]` 的字符串打印 `1`? [复制]