Pointer dereference array index

旧街凉风 提交于 2020-06-01 07:36:45

问题


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?


回答1:


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.




回答2:


For starters you should correctlyg specify the size of the allocated memory

   ar = malloc( 2 * sizeof( struct Test * ) );

This statement

*(ar+1) = &foo;

sets the second element of the allocated array of pointers to the address of the global variable foo.

It is the same as

ar[1] = &foo;

This expression

*ar

that is equivalent to the expression

ar[0]

gives the first element of the allocated array of pointers. It was not initialized. As a result this expression

*ar+1

or

ar[0] + 1

invokes undefined behavior (Adding 1 to something that was not initialized and has indeterminate value).

It seems you mean

(**(ar+1)).c = 'c';

That is the expression

*( ar + 1 )

gives the second element of the allocated dynamically array of pointers. Dereferencing it you get the address of the object foo. Dereferencing the second time you get lvalue of the object foo itself.

Pay attention to that the expression

ar[1]

is equivalent to

*( ar + 1 )

and as you can see from this valid statement

ar[1]->c = 'c'

the above expression yields a pointer. So you need to dereference it if you want to use the operator.

**( ar + 1 )



回答3:


You want to dereference to get ar[i], let's do as:

(*(ar+1))->c = 'c';


来源:https://stackoverflow.com/questions/61668742/pointer-dereference-array-index

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!