What is the purpose of (int *) p here?

131 views Asked by At

C newbie here and today I was reading about pointers and 2D arrays from a book and I came across this program

#include <stdio.h>

int main() {
    int s[4][2] = {
        { 1234, 56 },
        { 1212, 33 },
        { 1434, 80 },
        { 1312, 78 }
    };

    int(*p)[2];
    int i, j, *pint;
    for (i = 0; i <= 3; i++) {
        p = &s[i];
        pint = (int*)p;
        printf("\n");
        for (j = 0; j <= 1; j++)
            printf("%d ", *(pint + j));
    }

    return 0;
}

I really want to know what is the purpose of (int *) p; here. From what I can understand here that p is the pointer which stores the address of the entire i th row of the 2D array but I am not being able to understand the purpose of (int *) p; and storing it in a variable pint.

3

There are 3 answers

1
Barmar On

p is a pointer to an array of 2 integers. Casting that to int* makes it a pointer to a single integer, so it points to the first integer in the array. This is stored in the pint variable, which is declared int*.

This allows you to index the array by adding an offset to pint. In the printf() call, *(pint+j) is equivalent to pint[j], so the inner loop prints each element of the row of s.

4
trxgnyp1 On

The pointer here is a bit redundant, but you need to understand that accessing an index in C is the same as addition.

int arr[n];

arr[i] = 5;
// Is translated into
*(arr + i) = 5;

When you add to a pointer in C, it multiplies the index (i) by the size of each element to get the final address you are trying to access. Keep in mind that since arr is an array of int's, each element will be 4 bytes.

If the first element of arr is located at 0x1000, then (arr + 1) (i.e. arr[1]) will be at 0x1004.

When doing p = &s[i];, you are saving the address of the inner array into the pointer p:

p = &s[2];

int s[4][2] = {
    { 1234, 56 },
    { 1212, 33 },
    { 1434, 80 },
//  ^ p
    { 1312, 78 }
};

Then you cast it into pint which is a pointer to an integer, rather than a pointer to an array of 2 integers. The information is still the same, an address in memory, but the C compiler now interprets it diferently.

Then you add j to that pint pointer, which is the same ass doing pint[j], p[j] or *(p + j):

int s[4][2] = {
    { 1234, 56 },
    { 1212, 33 },
    { 1434, 80 },
//          ^ pint[1]
    { 1312, 78 }
};
0
August Karlstrom On

The type cast is needed in the assignment pint = (int *) p because pint and p have different types; pint is a pointer to an integer whereas p is a pointer to an array of two integers. The assignment makes pint point to the first integer of the i:th row in the matrix. Note that p + m will advance the pointer by matrix rows whereas pint + m will advance the pointer by matrix elements (integers).

We should also observe that the program is an obscure way of printing the elements in a matrix. Here is how you would normally do it:

#include <stdio.h>

#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])

int main(void)
{
    int s[][2] = {
        {1234, 56},
        {1212, 33},
        {1434, 80},
        {1312, 78}
    };
    int i, j;

    for (i = 0; i < LEN(s); i++) {
        for (j = 0; j < LEN(s[0]); j++) {
            printf("%d ", s[i][j]);
        }
        printf("\n");
    }
    return 0;
}