0

为什么下面代码中的赋值编译失败?

struct foo
{
  int* m_NormalIntPointer;
  int* volatile m_IntPointerModifiedByManyThreads;


  void func()
  {
     //compiles fine
     void* pointerToNormalPointer = &m_NormalIntPointer;

     //does not compile
     void* volatile* pointerToPointerModifiedByManyThreads = &m_IntPointerModifiedByManyThreads;
  }
};

如果 m_IntPointerModifiedByManyThreads 是指向 int 的指针,并且该指针可以被其他线程修改,而“void* volatile*”是指向可以被其他线程修改的指针的指针,为什么赋值需要强制转换,其中非易失版本没有?

4

1 回答 1

1

这一行:

void* volatile* pointerToPointerModifiedByManyThreads = &m_IntPointerModifiedByManyThreads

它是指向 a 的指针(void *)。让我们忽略它易变的事实,因为它无关紧要。(让我们也忽略您在volatile应该使用原子时使用的事实:volatile对于多线程编程几乎没有用处。)

您不能将指向指针转换为指向(void *)指针,(int *)反之亦然。就像您无法在指向指针struct x和指向指针之间进行转换一样,您也无法在指向指针和指向指针struct y之间进行转换。不允许这些转换。(int *)struct x

struct x my_x;
struct y *my_yptr = &my_x; // not allowed

int *my_intptr;
void **my_voidptr = &my_intptr; // not allowed, for exact same reason

唯一允许的转换是在指针void和其他指针之间。

int my_int;
void *my_voidptr = &my_int; // allowed
int *my_intptr = my_voidptr; // allowed

因此,如果要进行转换,则必须转换为void *,而不是void **. 因为int **是一个指针,你可以将它转换void *回来。

以下代码是正确的,但很难看:

int x = 3, y = 4;
int *my_intptr = &x;
void *my_intptr_ptr = &my_intptr;
*(int **) my_intptr_ptr = &y;
**(int **) my_intptr_ptr = 7;
// now y = 7, and my_intptr = &y
于 2013-10-19T21:36:38.613 回答