2008-12-03 181 views
39

我知道规则的拇指读声明从右到左,我相当肯定,我知道发生了什么事情,直到同事告诉我:在C和C++中,const指针指针指的是什么?

const MyStructure** ppMyStruct; 

的意思是“ppMyStruct是指针到一个const指针指向一个(可变的)MyStructure“(在C++中)。

我原以为这意味着“ppMyStruct是指向指向常量MyStructure的指针”。 我在C++规范中寻找答案,但显然我不是很擅长...

C++中的意思是什么,它是否意味着C中的同一事物?

回答

60

你的同事是错的。这是一个指向常量MyStructure的(非常量)指针的(非常量)指针。在C和C++中。

+6

这也是你有时会看到替代的部分原因“的拼写建议:MYSTRUCTURE常量* * ppMyStruct;然后,你可以阅读从右到左:指向常量Mystructure的指针 – 2008-12-03 14:00:11

+0

谁读取RTL?当然,我的客户都不::*)*我认为我们不需要RTL支持,我们是吗?* – dom0 2013-07-27 19:14:32

+0

这是一个旧帖子,所以可能是我的comment-qustion将不会被回答:如何创建一个const指针指向const MyStructure指针? – tchronis 2015-01-31 15:22:26

58

在这种情况下,工具的cdecl(或C++ DECL)可以是有益的:

 [[email protected] ~]$ cdecl explain "const struct s** ppMyStruct" 
    declare ppMyStruct as pointer to pointer to const struct s 
+1

非常有用。为什么这个工具不是众所周知的? – 2008-12-03 10:59:31

+0

你碰巧知道它是否适用于Windows? – Niklas 2008-12-03 11:03:56

5

你的同事是错误的,它是C和C++一样。请尝试以下操作:

typedef struct foo_t { 
    int i; 
} foo_t; 

int main() 
{ 
    foo_t f = {123}; 
    const foo_t *p = &f; 
    const foo_t **pp = &p; 
    printf("f.i = %d\n", (*pp)->i); 
    (*pp)->i = 888; // error 
    p->i = 999;  // error 
} 

的Visual C++ 2008给出了最后两行以下错误:

error C2166: l-value specifies const object 
error C2166: l-value specifies const object 

GCC 4说:

error: assignment of read-only location '**pp' 
error: assignment of read-only location '*p' 

G ++ 4说:

error: assignment of data-member 'foo_t::i' in read-only structure 
error: assignment of data-member 'foo_t::i' in read-only structure 
18

你说得对。这里有另外一种看待它的方法:

const MyStructure *  *ppMyStruct;  // ptr --> ptr --> const MyStructure 
     MyStructure *const *ppMyStruct;  // ptr --> const ptr --> MyStructure 
     MyStructure *  *const ppMyStruct; // const ptr --> ptr --> MyStructure 

这些是带有一个const限定符的指针指针的所有替代方法。从右到左的规则可以用来破译声明(至少在C++中;我不是C专家)。

5

是正确的。

Another answer已经指向“0​​”。虽然我非常喜欢那个,但有点精细。

3

作为其他评论的推论,不要把'const'放在第一位。它真的属于类型之后。这会马上澄清的意思,只是读它RTL像往常一样:

MyStructure const** ppMyStruct; 
0
void Foo(int  *  ptr, 
      int const *  ptrToConst, 
      int  * const constPtr, 
      int const * const constPtrToConst) 
{ 
    *ptr = 0; // OK: modifies the pointee 
    ptr = 0; // OK: modifies the pointer 

    *ptrToConst = 0; // Error! Cannot modify the pointee 
    ptrToConst = 0; // OK: modifies the pointer 

    *constPtr = 0; // OK: modifies the pointee 
    constPtr = 0; // Error! Cannot modify the pointer 

    *constPtrToConst = 0; // Error! Cannot modify the pointee 
    constPtrToConst = 0; // Error! Cannot modify the pointer 
}