-2

A[0] and A[1] are clearly pointers without any doubt which point to respective arrays. But shouldn't A be a pointer as well pointing to A[0] because compileing printf("%d", A) in GCC results in the following error:

format %d expects argument of type int, but argument 2 has type int *

If A is not a pointer then why is it considered a pointer when defining 2D matrix using pointers.

Moreover, printf("%d", *(A+1)[0]); works pretty fine implying that A is rendered as a pointer. And if that is the case printf("%d", A) should print the address of A[0] but it shows compilation error.

Christian Gibbons
  • 4,272
  • 1
  • 16
  • 29
Hackarp
  • 61
  • 1
  • 1
  • 6
  • 4
    *"A[0] and A[1] are clearly pointers without any doubt"* - no, they aren't – UnholySheep May 01 '19 at 13:34
  • Pointers and arrays are not synonymous. Pointers can use array notation to access, but they are different constructs with different properties. – Christian Gibbons May 01 '19 at 13:34
  • *"shouldn't A be a pointer as well [...] argument 2 has type `int*` "* I don't see the problem. It's saying that it's a pointer right there. Either way it would help illustrating your problem if you posted code that shows how `A` is defined. – Blaze May 01 '19 at 13:34
  • @Blaze My interpretation of the question is that OP expects it to be `int **` – Christian Gibbons May 01 '19 at 13:35
  • 2
    @ChristianGibbons I think you're right. Perhaps the OP can clarify by posting the code that leads to this issue. – Blaze May 01 '19 at 13:37
  • The format specifier for pointer values is `%p`, not `%d`. Using `%d` for printing a pointer value is UB. – Jabberwocky May 01 '19 at 13:38
  • `printf("%d", *(A+1)[0])` compiles fine because the type of `*(A+1)[0]` is `int`, but the type of `A` is not `int` but `int[2][2]` (or more or less `int*`). – Jabberwocky May 01 '19 at 13:41
  • You might like section 6 of [the C faq](http://c-faq.com/). – pmg May 01 '19 at 13:59
  • This question does not show a definition of `A` and is therefore unclear. The “A[m][n]” in the title might be intended to be part of a definition of `A`, but it is unclear. – Eric Postpischil May 01 '19 at 14:03
  • 1
    Post definition of `A`. – chux - Reinstate Monica May 01 '19 at 14:25
  • @Hackarp: although the question is now marked as a duplicate, you can accept one of the answers by clicking on the grey checkmark below its score. – chqrlie May 01 '19 at 15:51
  • @chux The only definition resembling an array (`A`) that can be interpreted by the compiler as a pointer (that I can think of) is when it is an argument of a function. – alx - recommends codidact May 01 '19 at 21:57

2 Answers2

1

This question boils down to whether or not arrays are pointers, which is not the case. See this question: Arrays are Pointers?.

When you use

int arr = {1, 2, 3, 4};
int *p = arr;

arr is converted from an array of ints to a pointer to an int. It is the same as doing.

int *p = &arr[0]

The same is happening with

printf("%d", A)

Which is why the compilers gives you the message, but this can be confusing and might lead one to think that pointers and arrays are indeed the same.

SilverTear
  • 695
  • 7
  • 18
1

There are many different ways to create so-called 2D matrices of int, each defining a very different type of object:

  1. as an array of arrays of int:

    int A[ROWS][COLS] = { 0 };
    
  2. as an array of pointers to arrays of int:

    int *A[ROWS];
    for (int i = 0; i < ROWS; i++)
        A[i] = calloc(sizeof(int), COLS);
    
  3. as pointer to an array of arrays of int:

    int (*A)[COLS] = calloc(sizeof(*A), ROWS);
    
  4. as a pointer to an array of pointers to arrays of int:

    int **A = calloc(sizeof(*A), ROWS);
    for (int i = 0; i < ROWS; i++)
        A[i] = calloc(sizeof(int), COLS);
    

In all cases, the syntax to access the matrix elements is the same: A[row][col], or any of the equivalent pointer notation variants:

    *(*(A + row) + col)
    *(A[row] + col)
    (*(A + row))[col]

In all cases, A, and A[row] can be used where a pointer is expected, either because they are indeed pointers (cases 3 and 4) or because arrays (cases 1 and 2) decay to a pointer to their first element when used in an expression context (except as an argument to sizeof), such as when passed as an argument to printf.

Printing pointer values with printf requires the %p conversion format.

%d expects an int, which is not the same as a pointer, may have a different size and may be passed to printf differently, all causing undefined behavior. The compiler emits a very useful warning about this. It is a good idea to configure the compiler with as many warnings as possible to detect silly mistakes.These warnings are sometimes difficult to understand, but are almost always an indication of something that needs fixing.

You can use printf("%p", (void*)A) which is equivalent to printf("%p", (void*)&A[0]) and printf("%p", (void*)A[0]), equivalent to printf("%p", (void*)&A[0][0]). All 4 should print the same address.

chqrlie
  • 131,814
  • 10
  • 121
  • 189