简体   繁体   中英

Assigning pointer from two-dimensional array

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

int main(void)
{
    int ar[2][2] = {1,2,3,4};
    int **p= NULL , i=0, j=0;

    p = ar;             //compiler error. Confused ! Do i need to assign &a or anything. 

    puts("OUT: ");

    for(i = 0; i < 2; i++)
    {
        for(j = 0 ; j < 2; j++)
        {
            printf("%2d", *(*(ar + i) +  j));
            printf("%2d", *(*(p + i) + j)); /* This is wrong . Compiler error */
        }
    }
    exit(0);
}

I want to create a pointer to the 2D array so that instead of ar in the for loop i should be able to put p . I'm confused. I know other methods of accessing 2d elements but i'm confused with this example.

In the first case you have an array of int[2] , while in the second case you have an array of int*.

If you use sizeof(ar[0]) , it would print 2*sizeof(int) , while the second would print sizeof(int*) .

  printf("sizeof(ar)       = %zu\n", sizeof(ar));
  printf("sizeof(ar[0])    = %zu\n", sizeof(ar[0]));
  printf("sizeof(ar[0][0]) = %zu\n", sizeof(ar[0][0]));
  printf("sizeof(p)        = %zu\n", sizeof(p));
  printf("sizeof(*p)       = %zu\n", sizeof(*p));
  printf("sizeof(**p)      = %zu\n", sizeof(**p));

Since I tried you code, replaced p = a with p = ar I only have these errors:

$ gcc -Wall foobar.c 
foobar.c: In function ‘main’:
foobar.c:6:3: warning: missing braces around initializer [-Wmissing-braces]
foobar.c:6:3: warning: (near initialization for ‘ar[0]’) [-Wmissing-braces]
foobar.c:12:5: warning: assignment from incompatible pointer type [enabled by default]
foobar.c:21:7: warning: too many arguments for format [-Wformat-extra-args]

And it fails too:

$ ./a.out 
sizeof(ar)       = 16
sizeof(ar[0])    = 8
sizeof(ar[0][0]) = 4
sizeof(p)        = 8
sizeof(*p)       = 8
sizeof(**p)      = 4
OUT: 
Segmentation fault

Which is normal, assuming p is not so well defined.

ar[2][2] will NOT decompose into pointer to pointer int **p=ar //is wrong ,It will be decomposed into Pointer to first row(if we think in matrix form, which i think its easy),this means in your example your 2-d array consists of 2 rows,Each row has 2 integers(columns).

Hence ar will be decomposed into pointer to 2 integers, Which can be programmatically declared as

int (*p)[2]; //this is pointer to 2 ints
int (*p)[3]; //this is pointer to 3 ints,if your array was declared like this ar[2][3]

So in your program you need to change int **p=NULL to int (*p)[2];

When we say a pointer to 2 integers,it means that When you add one (ex:- p+1) for above example then this will point to the next two integers of 2-d array(which means next row).

a quote from comp.lang.c FAQ list, Question 6.18

The rule (see question 6.3) by which arrays decay into pointers is not applied recursively. (Once the rule has been applied once, the result is a pointer to which the rule no longer applies.) An array of arrays (ie a two-dimensional array in C) decays into a pointer to an array, not a pointer to a pointer.


int ** and int [2][2] are not compatible. you should think of your ar array as of an array that holds another arrays. multidimensional arrays allocated on stack are stored in memory continguously.

statement int ar[2][2] will be changed by the compiler to int (*ar)[2] . notice the placement of parentheses. this is because of operators precedence:

  • () operator has higher precendece than [] operator
  • [] operator has higher precedence than * operator.

. so if you would omit them, then:

int *ar[2];  // ar is an array of length 2 that holds pointers to ints.
int (*ar)[2];  // ar is a pointer to array of length 2 that hold ints.

you can resolve your problem by:

  • changing int **p = NULL; to int (*p)[2];
  • changing int ar[2][2] to int **ar and then properly allocate memory for rows and columns using malloc()

think of how that 2d array is subscripted. for example, the statement:

printf("%2d ", *(*(ar + 1) +  1));  // print the ar[1][1]

adds 1 to ar pointer, which points to int [2] . 8 bytes are added to the address of beginning of array, then after dereference adding 1 will add only 4 bytes, since it refers now to int.

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

int main(void)   
{    
    const int row=4, col=4;
    int ar[row][col] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
    int **p= NULL ; 
    int *np =  &ar[0][0];            
    p = &np;

    for(int i = 0; i < row; i++)
    {
       for(int j = 0 ; j < col; j++)
       {
            printf("address of a[%d][%d] is %x\n",i,j,&ar[i][j]);
            printf("%2d\n", *(*(ar + i) +  j));
            printf("%2d\n", *(*(p)+ i*col  + j));
       }
    }

    _getch();
    exit(0);
}

i tried like this, it worked for me.

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