c – 为什么抛出指向原始类的指针的奇怪行为?

前端之家收集整理的这篇文章主要介绍了c – 为什么抛出指向原始类的指针的奇怪行为?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
假设在我的代码中我必须将void *存储为数据成员,并在需要时将其强制转换回原始类指针.为了测试它的可靠性,我写了一个测试程序( linux ubuntu 4.4.1 g -04-Wall),我很震惊地看到了这个行为.
struct A
{
  int i;
  static int c;
  A () : i(c++) { cout<<"A() : i("<<i<<")\n"; }
};
int A::c;

int main ()
{
  void *p = new A[3];  // good behavior for A* p = new A[3];
  cout<<"p->i = "<<((A*)p)->i<<endl;
  ((A*&)p)++;
  cout<<"p->i = "<<((A*)p)->i<<endl;
  ((A*&)p)++;
  cout<<"p->i = "<<((A*)p)->i<<endl;
}

这只是一个测试程序;实际上,对于我的情况,必须将任何指针存储为void *,然后将其强制转换回实际指针(借助模板).所以我们不要担心这一部分. output of the above code是,

p->i = 0
p->i = 0 // ?? why not 1
p->i = 1

但是如果你改变了void * p;到A * p;它给了expected behavior.为什么?

另一个问题,我无法逃避(A *&),否则我不能使用操作符;但它也发出了警告,dereferencing type-punned pointer will break strict-aliasing rules.有没有可行的方法来克服警告?

解决方法

好吧,正如编译器警告你的那样,你违反了严格的别名规则,这正式意味着结果是未定义的.

您可以通过使用增量的函数模板来消除严格的别名冲突:

template<typename T>
void advance_pointer_as(void*& p,int n = 1) {
    T* p_a(static_cast<T*>(p));
    p_a += n;
    p = p_a;
}

使用此函数模板,main()的以下定义会在Ideone编译器上生成预期结果(并且不发出警告):

int main()
{
    void* p = new A[3];
    std::cout << "p->i = " << static_cast<A*>(p)->i << std::endl;
    advance_pointer_as<A>(p);
    std::cout << "p->i = " << static_cast<A*>(p)->i << std::endl;
    advance_pointer_as<A>(p);
    std::cout << "p->i = " << static_cast<A*>(p)->i << std::endl;
}
原文链接:https://www.f2er.com/c/117081.html

猜你在找的C&C++相关文章