通过指向指针的指针访问结构体元素的地址

5
假设我有一个结构体:
struct ABC 
{
   char a;
   char b;
   char c;
}

我可以声明一个指向上述结构的指针的指针,如下所示:struct ABC** abc。现在,abc是指向结构指针*abc的指针,而*abc是指向结构abc的结构指针。因此,sizeof(**abc)为4,sizeof(*abc)也为4,sizeof(abc)为3(考虑指针大小为4字节,字符大小为1字节)。
我的问题是:如何使用上面声明的 abc 声明一个指向成员变量 c 的字符指针?

11
标题直接来自于《大卫·林奇的C++》,由哈里·迪恩·斯坦顿扮演的新操作员。 - Kerrek SB
9
好的,请稍等片刻。哦,拜托了...修改你的标题吧! - Lightness Races in Orbit
1
那是一个相当棘手的“主题”!怎么样,简单点说,“声明结构体成员的指针”?或者有其他摘要吗? - abelenky
1
@abelenky:那将是一个更糟糕的标题。在列表中命名语言特性是没有用的! - Lightness Races in Orbit
2
来吧,伙计们,这是一个引人注目且相当幽默的标题 :) - Jimbo
显示剩余10条评论
6个回答

5
sizeof(**abc) will be 4, sizeof(*abc) will also be 4 and sizeof(abc) will be 3 

我认为,假设结构体没有填充的情况下,应该是这样的:
sizeof(**abc) will be 3, sizeof(*abc) will also be 4 and sizeof(abc) will be 4
                     ^^^                                                    ^^^  
                      Change here                                           change here

为了获取成员变量 c 的指针,请执行如下操作:
&(*abc)->c

注意*abc周围的圆括号。原因是->*具有更高的优先级,因此您需要确保第一次解引用(从指向指针的指针到指针)首先发生。
或者您也可以这样做:
&(**abc).c

括号的原因也是一样的...需要确保在应用对象名称的成员选择之前,已经进行了两次取消引用。

.


4

如果您提供的所有指针都是有效的,以便您可以对它们进行解引用,那么您可以按照以下方式执行:

char* a_ptr = &((*abc)->a);
or 
char* b_ptr = &((**abc).b);

3
你的意思是像这样吗?
char *c = &((**abc).c);
char *d = &((*abc)->c);

或者您可以写一些易读的内容:

ABC **pp == foo();
ABC *p = *pp;
char *c = &(p->c);

在写这篇文章时,我意识到我甚至不了解导致这个问题的思考过程。让我们来分析一下:

  1. Q: from a structure reference, how do I get a member reference?

    • A: using the member access operator .

      char &c = r.c;
      
  2. Q: from a structure reference, how do I get a pointer to a member?

    • A: using the address operator &

      char *c = &r.c;
      
  3. Q: from a structure pointer, how do I get a member reference?

    • A: using the member access operator ->

      char &c = p->c;
      
  4. Q: from a structure pointer, how do I get a pointer to a member?

    • A: if only there were some way to combine 2 and 3!

      char *c = &p->c;
      
  5. Q: from a pointer to a pointer, how do I get a regular pointer?

    • A: using the dereference operator *

      ABC **pp = foo();
      ABC *p = *pp;
      
  6. Q: from a pointer to a pointer to a structure, how do I get a pointer to a member?

    • A: Left as an exercise for the reader

请问在这个过程中哪一步骤引起了困难?


非常抱歉,先生,但我自己无法正确地完成这些步骤。我遇到了很多错误。很抱歉我不得不问这个问题。 - Chani
1
不用道歉!不过,如果您能展示一下您尝试过什么以及出现了哪些错误,那可能会有所帮助。没有这些信息,我们只能猜测您可能犯了哪些错误。 - Useless

3

由于您的问题中使用了一些略微奇怪的命名法,因此有几种解释方法。我将在这里探讨两种。


方案1

您有一个ABC对象,并且您想要指向该对象内部的一个char成员的指针。

好吧,这就是这个对象:

ABC obj;

这里是目前您提到的指针:

ABC*  ptr1 = &obj;
ABC** ptr2 = &ptr1;

这里是你所要求的指针,有三种等效的声明方式:

char* theChar1 = &(obj.c);
char* theChar2 = &(ptr1->c);
char* theChar3 = &((*ptr2)->c);

场景2

您没有一个ABC对象,但您希望获得一个指向成员c的指针,以后可以将其应用到一些稍后获取的ABC对象的成员。

不,您不需要。


3

&(*abc)->c,但出于易读性的考虑,您可能需要逐步进行:

struct ABC *foo = *abc;
char *bar = &foo->c;

2
如何声明一个字符指针,该指针指向上面声明的abc中的成员变量c?
可以这样声明:
char *p = &(*abc)->a;

它声明p为指向char的指针,并且p指向结构体成员a。括号是必需的,因为后缀运算符比一元运算符具有更高的优先级。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接