简体   繁体   中英

Working of Pointers and Arrays in C

I'm using Visual Studio 2013 for C.

main.c

int main()                          
{
    int arr[2][3] = { { 10, 20, 30 }, { 15, 25, 35 } };
    int **pArr = arr;

    printf("\n\n----SIZE OF----");
    printf("\nSizeOf(arr) = %d", sizeof(arr));
    printf("\nSizeOf(pArr) = %d", sizeof(pArr));

    printf("\n\n----DEREFERENCING THE ADDRESS----");
    printf("\narr = %d   *arr = %d   **arr = %d", arr, *arr, **arr);
    printf("\npArr = %d   *pArr = %d   **pArr = %d", pArr, *pArr, **pArr);    //EXCEPTION thrown here

    return 0;
}

Check out this image for a thrown exception:

例外

On using the break-point the values in pointer pArr & array arr are shown:

关于调试

But when I removed the **pArr part from the second last line of the code, the program output this:

----SIZE OF----
SizeOf(arr) = 24
SizeOf(pArr) = 4

----DEREFERENCING THE ADDRESS----
arr = 5569760   *arr = 5569760   **arr = 10
pArr = 5569760   *pArr = 10

Pointer pArr is of type "pointer to pointer to int", and therefore is the address at arr . Then why can't I access **pArr after using int **pArr = arr; ?

You get an error because *pArr yields the first element of your 2D array which is 10.
Then, by writing **pArr in your last printf you try to dereference 10 which is in hexadecimal 0xa thus the error message.

Change

int **pArr = arr;

To

int *Arr = arr;
int **pArr = &Arr;

Since pArr is a pointer to a pointer of type int , you are trying to point it just to a pointer. so when trying to dereferencing an unknown memory location causes Segmentation fault

Edit:
Consider int arr[] ;
Here &arr and arr are memory location. (arr+2) to get the address of arr[2], but not ((&arr)+2) to do the same. Similarly, pArr is pointing to arr . When you write *pArr it is same as **arr

Refer Please explain the difference for more info

Your array arr and pArr contains address 0x60f914 . The memory here contains 6 integers are you have initialized.

When your do *pArr it will give you contains at address 0x60f914 which is 10 . And when you do **pArr it will give you contains at address 10 .

So the conclusion is 2-D array is not exactly arranged as _pointer-to-pointer-to-int`.


Update:

This is similar to type-casting. If you have some memory address (eg void * ) you can type cast it to anything ( int * or my_struct * ) and access the contains of it. But this does not guarantee that structure and contains of that memory is valid for typecasting you are trying to do.

If you use 1-D array, arr it is pointer to base value of array arr. That is it is as good as &arr[0] .

When you use 2-D array arr represents pointer to base value, that is arr[0] which is (*arr)[3] .

So you should use,

int (*pArr)[3] = arr;

Instead of

int **ptr = arr;

A multidimensional array is a compiler construct. It is a continuous memory area whose the position is abstracted away by the compiler. A computer's physical memory layout is purely single dimensional (a huge array).

So, this following code:

int **pArr = arr;

It translates in the following assembly:

   6:hhh1.c         ****     int **pArr = arr;
  41                    .loc 1 6 0
  42 0032 488D45E0      leaq    -32(%rbp), %rax
  43 0036 488945D8      movq    %rax, -40(%rbp)

And the following (correct) code:

 int (*pArr)[3] = arr;

Translates in the following assembly:

   6:hhh2.c         ****     int (*pArr)[3] = arr;
  41                    .loc 1 6 0
  42 0032 488D45E0      leaq    -32(%rbp), %rax
  43 0036 488945D8      movq    %rax, -40(%rbp)

Surprised that it translates exactly the same!? It's because the second code changes how the memory is fetch by the compiler later on your code.

Let's take a look in the assembly of the last printf or yours, the first being the one of the wrong code, and the second being from the right code:

  14:hhh1.c         ****     printf("\npArr = %d   *pArr = %d **pArr = %d", pArr, *pArr, **pArr);    //EXCEPTION thrown here
  71                    .loc 1 14 0
  72 00a0 488B45D8      movq    -40(%rbp), %rax
  73 00a4 488B00        movq    (%rax), %rax
  74 00a7 8B08          movl    (%rax), %ecx
  75 00a9 488B45D8      movq    -40(%rbp), %rax
  76 00ad 488B10        movq    (%rax), %rdx
  77 00b0 488B45D8      movq    -40(%rbp), %rax
  78 00b4 4889C6        movq    %rax, %rsi
  79 00b7 BF000000      movl    $.LC5, %edi
  79      00
  80 00bc B8000000      movl    $0, %eax
  80      00
  81 00c1 E8000000      call    printf

And now, the generated from using the second style:

  14:hhh2.c         ****     printf("\npArr = %d   *pArr = %d **pArr = %d", pArr, *pArr, **pArr);    //EXCEPTION thrown here
  71                    .loc 1 14 0
  72 00a0 488B45D8      movq    -40(%rbp), %rax
  73 00a4 8B08          movl    (%rax), %ecx
  74 00a6 488B55D8      movq    -40(%rbp), %rdx
  75 00aa 488B45D8      movq    -40(%rbp), %rax
  76 00ae 4889C6        movq    %rax, %rsi
  77 00b1 BF000000      movl    $.LC5, %edi
  77      00
  78 00b6 B8000000      movl    $0, %eax
  78      00
  79 00bb E8000000      call    printf

Wow! See now? It's different.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM