指针解引用数组索引 [英] Pointer dereference array index

查看:323
本文介绍了指针解引用数组索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

具有:

#include <stdio.h>
#include <stdlib.h>

struct Test { char c; } foo;

int main (void) {

   struct Test **ar;
   ar=malloc(16);
   *(ar+1) = &foo;
   ar[1]->c = 'c'; //this work
  (*(*ar+1)).c = 'c'; //this does't work

   return 0;
}
        //(**(ar+1)).c='c'; --> first case

为什么上面的方法仅适用于具有数组条目的变体而不是指针取消引用?

struct Test { char c; } foo;

int main (void) {

   struct Test **ar;
   ar=malloc(16);
   *ar=malloc(0);
   *(ar+1) = &foo;
   //(**(ar+1)).c='c';
   (*(*ar+1)).c='c'; // NOW IT WORKS --> second case
   printf("%c\n", (*(*ar+1)).c); //prints 'c'

   return 0;
}

现在甚至分配了0个字节,这没关系,因为我只想由OS提供一个地址来初始化第一个元素

问题:指针算术在两种情况下如何工作? 据我了解:

1)首先,为了获得struct Test的左值,指针直接从ar的指向地址移动到**ar-sizeof(struct Test**)

的左值

2)在第二种情况下,指针确实已经初始化了第一个成员ar[0],因此它从*ar开始,并通过*ar-sizeof(struct Test*)到达左值.

但是两个指针的大小都相同sizeof(struct Test**) == sizeof(struct Test*),因此算术上不应有差异,否则我会遗漏某些东西吗?

解决方案

struct Test **ar;
ar=malloc(16);
...
(*(*ar+1)).c = 'c'; //this does't work

当然可以.如我的评论所述,*的优先级高于+ C运算符优先级.那么(*(*ar+1)).c中发生了什么?看:

(*ar+1)

等效于:

(ar[0] + 1)

因为ar类型指向的指针到 struct Test,所以*arar[0]都是 pointer指针- struct Test.然后添加+ 1,这会将sizeof (struct Test*)添加到所需的第一个指针ar中.

为什么行得通?运算符优先级:

   *ar              /* dereference ar** leaving pointer to struct Test */

  (*ar + 1)         /* advance to next pointer - applied before next dereference */

 *(*ar + 1)         /* dereference again leaving struct Test assigned to 2nd pointer */

(*(*ar + 1)).c      /* reference member 'c' of above */

在使用多个间接级别时,可读性至关重要.使用索引符号将有很大帮助.代替(*(*ar + 1)).c = 'c';,它更容易编写:

(*ar)[1].c = 'c';

这清楚地表明,在应用1的偏移量之前,您首先要对ar进行引用,然后再次进行引用(与'*'相同的是[..]进行引用),以达到分配的第二个Poitner.

>

Having this:

#include <stdio.h>
#include <stdlib.h>

struct Test { char c; } foo;

int main (void) {

   struct Test **ar;
   ar=malloc(16);
   *(ar+1) = &foo;
   ar[1]->c = 'c'; //this work
  (*(*ar+1)).c = 'c'; //this does't work

   return 0;
}
        //(**(ar+1)).c='c'; --> first case

Why the above works only the variant with array entry and not pointer dereference?

struct Test { char c; } foo;

int main (void) {

   struct Test **ar;
   ar=malloc(16);
   *ar=malloc(0);
   *(ar+1) = &foo;
   //(**(ar+1)).c='c';
   (*(*ar+1)).c='c'; // NOW IT WORKS --> second case
   printf("%c\n", (*(*ar+1)).c); //prints 'c'

   return 0;
}

Now even allocated 0 bytes, that doesnt matter since I just want an address provided by OS in order to have the first element initilalized

question: how does pointer arithmetic works in both cases? As I understand the them:

1) first In order to get to lvalue of struct Test, the pointer goes directly from the pointed address by ar to the lvalue by **ar - sizeof(struct Test**)

2) in second case, the pointer does have initialized the first member ar[0], so it starts here *ar and goes to the lvalue by *ar - sizeof(struct Test*).

But both pointers have same size sizeof(struct Test**) == sizeof(struct Test*), and therefor shouldn't be difference in arithmetic, or I am missing somehting?

解决方案

struct Test **ar;
ar=malloc(16);
...
(*(*ar+1)).c = 'c'; //this does't work

Of course it does. As noted in my comment * has higher precedence than + C Operator Precedence. So what is happening in (*(*ar+1)).c? Look at:

(*ar+1)

which is equivalent to:

(ar[0] + 1)

Since the type for ar is a pointer-to-pointer-to struct Test, *ar or ar[0] is type pointer-to struct Test. Then you add + 1 which adds sizeof (struct Test*) to the first pointer ar which is what you want.

Why does that work? Operator precedence:

   *ar              /* dereference ar** leaving pointer to struct Test */

  (*ar + 1)         /* advance to next pointer - applied before next dereference */

 *(*ar + 1)         /* dereference again leaving struct Test assigned to 2nd pointer */

(*(*ar + 1)).c      /* reference member 'c' of above */

Readability is critical when playing with multiple levels of indirection. Using index notation will help greatly. Instead of (*(*ar + 1)).c = 'c';, it is much cleaner to write:

(*ar)[1].c = 'c';

That conveys clearly you are dereferencing ar first before applying the offset of 1 and dereferencing again (the [..] provides a dereference just as '*' does) to reach the 2nd of your allocated poitners.

这篇关于指针解引用数组索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆