C++ 为什么我可以将void*强制转换为int*而不是int*&;?

C++ 为什么我可以将void*强制转换为int*而不是int*&;?,c++,pointers,casting,C++,Pointers,Casting,API使用void*存储非类型指针偏移量。这有点老套,不过没关系 为了表达我的偏移量算法,我试着做这样的事情 int main () { void * foo; foo = static_cast <int *> (nullptr) + 100; static_cast <int * &> (foo) += 100; } 解决方法很简单: foo = static_cast <int *> (foo) + 100; fo

API使用
void*
存储非类型指针偏移量。这有点老套,不过没关系

为了表达我的偏移量算法,我试着做这样的事情

int main ()
{
    void * foo;

    foo = static_cast <int *> (nullptr) + 100;

    static_cast <int * &> (foo) += 100;
}
解决方法很简单:

foo = static_cast <int *> (foo) + 100;
foo=static_cast(foo)+100;
但是为什么不允许第一个呢


在回答“因为标准这么说”之前,标准为什么这么说?第一种方法危险吗?还是仅仅是疏忽?

这是不允许的,原因与
inti;静态铸造(l)=3L是不允许的

当然,在很多实现中(其中
int
long
具有相同的大小、表示和对齐方式),它都可以工作。但是强制转换的有效规则对于所有实现都是相同的,显然这在
int
long
具有不同大小的平台上是不可能的,这意味着不可能允许在这些平台上访问一个

历史上,有一些实现在
void*
int*
上有不同的表示

后来,在标准规定像访问
int*
一样访问
void*
是无效的之后,实现也开始优化,假设有效的程序不会这样做:

void *f (void **ppv, int **ppi) {
  void *result = *ppv;
  *ppi = nullptr;
  return result;
}
允许实现对此进行优化,以

void *f (void **ppv, int **ppi) {
  *ppi = nullptr;
  return *ppv;
}

而这样的优化,当它们减少代码大小或提高效率时,如今已经司空见惯了。如果
f
被允许称为
void*pv=&pv;f(pv和静态浇铸(pv)),此优化将无效。由于这种优化被证明是有用的,因此规则不太可能改变。

理论上,不能保证
void*
int*
具有相同的大小。作为左值,它们可能不兼容。虽然这在实践中是不可能的。@lilistence:在实践中,
int*
所需的位比
void*
少,所以虽然这可能很少见,但它们实际上大小不同(与在
int*
中有两个未使用/填充位相比)也不是不可能的。最后一个例子很有说服力,以前我认为这些区别只是理论上的。通过对叮当声的测试,此优化甚至针对
-O1
。回答得很好,谢谢。但是为什么我的
x=static\u cast(x)+n
fix不被禁止?@spraff这就像
inti=3;i=静态压力(i)+1L。这里没有比特的重新解释,只有值的转换。即使
void*
int*
具有不同的表示形式,那么
static_cast(x)
将更改表示形式,
n
将被添加,隐式转换回
void*
将更改表示形式。
void *f (void **ppv, int **ppi) {
  *ppi = nullptr;
  return *ppv;
}