1

I have come across a C code similar to the following:

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

int main(void) {

    int *a = malloc(200*sizeof(int));

    int i;

    for (i = 0; i < 200; i++)
    {
      a[i] = i;
    }

    int (*b)[10] = (void*) a;

    printf("\nsizeof(int):\t%d\n", sizeof(int));

    printf("\nb[0]:\t%d\n", b[0]);
    printf("\na:\t%d\n", a);

    printf("\nb[19]:\t%d\n", b[19]);
    printf("\na+190:\t%d\n", a+190);

    printf("\nb[0][8]:\t%d\n", b[0][8]);
    printf("\nb[19][9]:\t%d\n", b[19][9]);

    return 0;
}

As per my understanding, the line int (*b)[10] = (void*) a; is trying to assign pointer b (which is supposed to point to an array of 10 integers) to the starting address of array a typecast as a void pointer. I would have expected b[i] to hold the same data as a[i] for i=0..9 (and any index other than 0 to 9 for b resulting in some undefined behavior). However, the program produces outputs similar to the following sample:

sizeof(int):    4

b[0]:   9768976

a:      9768976

b[19]:  9769736

a+190:  9769736

b[0][8]:        8

b[19][9]:       199

Clearly, b has become an array of 20 pointers, with each elemental pointer pointing to a unique portion of the a array corresponding to 10 integers (or 40 bytes) each. Can someone please explain what exactly int (*b)[10] = (void*) a; does? Specifically, how does the typecast (void *) help in distributing the entire a across multiple elements of b? The above code would not compile without the (void *) cast.

7
  • "I would have expected b to be a pointer that can only access the first 10 elements of a" - so would you also expect that int *b = (void *)a; would only be able to access one int ? Commented Oct 4, 2016 at 0:08
  • No. I guess I did not express myself well in that sentence. I will edit my question to better explain what I meant. Commented Oct 4, 2016 at 0:13
  • b[0] is an array consisting of the first 10 ints, b[1] is the next 10 ints, and so on Commented Oct 4, 2016 at 0:14
  • Correct. That's what I figured from the output I posted. I am just not sure how this works inside the int (*b)[10] = (void*) a; statement. I could not find other such examples in my online searches. This seems like a way of creating separate pointers for chunks of a large array, something I have not come across earlier. Commented Oct 4, 2016 at 0:18
  • 1
    It's the same principle as int *b = (void *)a except you are pointing to 10 ints instead of pointing to 1 int. Commented Oct 4, 2016 at 0:40

2 Answers 2

0

Look at it like this:

int *a;
a = malloc(200 * sizeof(int));

int (*b)[10];
b = (void *)a;

So, the first line says that a should point to an int. The second line allocates a block of memory that can hold 200 ints, and assigns the address of the start of this block to a. The third line says that b should point to an array of 10 ints. The fourth line says that b should be assigned the address held by a.

So now b points to an array of 10 ints starting at the address returned from the call to malloc(). Since memory was allocated for 200 ints, b points to a block of memory that can hold 20 10-element arrays of int.

The cast to void is needed because a was declared to be a pointer to int; this allows you to store the value held by a in b, even though they are of different types. I think that this was a mere convenience in the allocation of the appropriate amount of memory for the array. An alternative method, avoiding the declaration of a altogether, would be:

int (*b)[10] = malloc(20 * sizeof(*b));

This second method might or might not seem a bit more cryptic, depending upon the readers tastes. I guess one advantage of the first method is that it allows you to access the elements of the array both sequentially and as a 2d array.

Sign up to request clarification or add additional context in comments.

Comments

0

Clearly, b has become an array of 20 pointers, with each elemental pointer pointing to a unique portion of the a array corresponding to 10 integers (or 40 bytes) each.

No, b is just a pointer, not an array. The type b points to is array-of-10-ints. Perhaps this would be simpler if you consider it as:

typedef int row[10]; // A `row` is an array of 10 ints
row* b = (void*) a;

For any pointer T* p, p[n] is sizeof (T) bytes offset from p[n - 1] (assuming that n and n - 1 are valid indices, of course). This case is no different; here T is a 10-element int array, so each element of b is 10 * sizeof (int) bytes away from its adjacent elements.

Specifically, how does the typecast (void *) help in distributing the entire a across multiple elements of b? The above code would not compile without the (void *) cast.

In C, pointers can be converted between void* and T* without explicit casting. The above case uses a void* cast for convenience by reducing typing; it allows the right-hand-side to be converted to whatever pointer type is needed by the left-hand-side.

3 Comments

Your example is finally getting me somewhere. So, int (*b)[10] should be interpreted as b being a pointer to a type that consists of a 10-interger array. Then, after assigning b to a larger memory portion (with >10 integers, such as the 200-integers pointed to by a in my question), we can access that memory in 10-element chunks by using indices for b, starting from b[0][0..9] or (*(b))[0..9] for the first 10 elements and b[19][0..9] or (*(b+19))[0..9] for the last 10.
@NI3 Also, if you found my answer helpful, you should upvote it. =)
@jamesdin Thanks. I have upvoted your answer. However, due to my new account, it's not visible yet. I need at least a reputation of 15 for my upvotes to matter.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.