Memory allocation for pointer to an array in c?

219 Views Asked by At
#include <stdio.h>
int main()
{
 int (*ptr) [5];
 printf ("%lu\n" , sizeof (ptr));
 printf ("%lu\n" , sizeof (*ptr));
}

I am using 64 bit system. When I run this code in gcc compiler it generate output 8 and 20 . My question is how many byte going to allocate for this pointer to an array ? It is 8 or 20 and why?

7

There are 7 best solutions below

0
John Bode On BEST ANSWER

ptr designates an object that will store the address of a 5-element array of int. On your system, such a pointer takes up 8 bytes of storage.

The expression *ptr can designate an object that is a 5-element array of int; on your system, such an array takes up 20 bytes (5 4-byte elements).

Assume the code:

int (*ptr)[5] = malloc( sizeof *ptr );

This gives you something like the following (each box takes up 4 bytes):

     +---+        +---+
ptr: |   | -----> |   | (*ptr)[0]  // we don't want to index into ptr,
     + - +        +---+            // we want to index into what ptr
     |   |        |   | (*ptr)[1]  // *points to*, hence the explicit
     +---+        +---+            // dereference on ptr.  
                  |   | (*ptr)[2]  //
                  +---+            // Since a[i] is defined as *(a + i),
                  |   | (*ptr)[3]  // (*ptr)[i] == (*(ptr + 0))[i] ==
                  +---+            // (ptr[0])[i] == ptr[0][i]
                  |   | (*ptr)[4]  //
                  +---+

sizeof  ptr == sizeof (int (*)[5]) ==  8 // assuming 8-byte addresses
sizeof *ptr == sizeof (int [5])    == 20 // assuming 4-byte int

This is equivalent to writing

int arr[5];            // sizeof arr == sizeof (int [5])    == 20
int (*ptr)[5] = &arr;  // sizeof ptr == sizeof (int (*)[5]) ==  8

The size of a pointer does not depend on the size of the thing it points to.

0
Ted Lyngmo On

My question is how many byte going to allocate for this point to an array ? It is 8 or 20 and why?

It depends on if you need to allocate memory for a pointer or for the memory it's pointing at.

You need to know the sizes of what you are looking at:

#include <stdio.h>

int main() {
    int(*ptr)[5];
    
    printf("%zu\n", sizeof ptr);     // size of a pointer - expression sizeof
    printf("%zu\n", sizeof(void*));  // size of a pointer - type sizeof
    printf("%zu\n", sizeof *ptr);    // size of an int[5] - expression sizeof
    printf("%zu\n", sizeof(int[5])); // size of an int[5] - type sizeof
}

Sidenote: %lu is not the correct conversion. Use %zu for sizeof.

3
Eric Postpischil On

My question is how many byte going to allocate for this point to an array ? It is 8 or 20 and why?

You do not allocate memory for the pointer to an array or other object. You allocate memory for the array or other object. The pointer is only used to point to it. It does not have any intrinsic association with the memory.

To allocate memory for an array or other object, you tell malloc how many bytes you need for the object. For example, void *p = malloc(12); allocates memory for any object in C that uses 12 bytes or fewer, as long as it does not have some extended alignment requirement. (All the basic objects in C, the standard integer, pointer, and floating-point types and the arrays, unions, and structures made of them, have fundamental alignment requirements that are satisfied by malloc.)

The sizeof operator will help you determine how many bytes are needed. You can give the sizeof operator a type such as int [5] for an array of 5 int, and it will give the correct number of bytes:

void *p = malloc(sizeof (int [5]));

Note that the type of p has nothing to do with the memory being allocated or what will be put into it. The pointer is just a pointer.

However, you can declare a pointer of an appropriate type and use it with sizeof. Given int *p;, then this code:

p = malloc(sizeof *p);

says to allocate enough memory for whatever type of object p points to. Note that you must use sizeof *p for the size of what p points to, not sizeof p, because sizeof p is the size of the pointer p, not the size of the type that p points to.

If p is to point to the first of an array of objects, you can multiply to get the size of the array:

p = malloc(5 * sizeof *p);

You could also use a pointer to an entire array, instead of an element, like this:

int (*p)[5] = malloc(sizeof *p);

There is no explicit multiplication by the number of elements because *p represents an entire array, not a single element of it. However, this form is not used often because then it is harder to use p to access elements of the array. Since *p is the whole array, instead of the first element, you need to use (*p)[i] to access element i. When p is a pointer to just the first element, you can access an element with p[i].

So declaring such a pointer as int *p is favored over int (*p)[5] except when there are additional circumstances for wanting to refer to the whole array.

0
Yasika Hivin Gunathilaka On

In your code, int (*ptr)[5]; declares a pointer to an array of 5 integers. Let's break down the size calculations:

  1. sizeof(ptr): This gives the size of the pointer itself. On a 64-bit system, a pointer typically takes up 8 bytes. So, sizeof(ptr) will be 8.

  2. sizeof(*ptr): This gives the size of the object that ptr points to, which is an array of 5 integers (int[5]). The size of an array is the size of one element multiplied by the number of elements. In this case, sizeof(int) is typically 4 bytes on most systems, and you have 5 elements. Therefore, sizeof(*ptr) will be 4 * 5 = 20.

So, the output you see (8 for sizeof(ptr) and 20 for sizeof(*ptr)) is correct. It means that the pointer itself takes up 8 bytes, and the array it points to (which is an array of 5 integers) takes up 20 bytes.

0
GuentherMeyer On

You declare ptr to be a pointer to an array of 5 integers. ptr holds the address which is 8 Bytes.

When you look up what is at the address (dereferencing) with *ptr you get the array of 5 integer which is 5*sizeof(int) = 5*4 = 20

Caution: There may be an address in ptr but there is no memory allocated at that address.

To do this you need to call ptr = malloc(sizeof(*ptr))

If you don't do this, access to the array will segfault. For example *ptr[0]=0;

0
Vlad from Moscow On

The sizeof operator may be applied to a complete object type.

You declared a pointer to an array of the type int[5].

int (*ptr) [5];

This call of printf

printf ("%lu\n" , sizeof (ptr));

yields the size of the pointer. Pay attention to that pointers are always complete types.

The *ptr has the complete array type int[5] . So this call of printf

printf ("%lu\n" , sizeof (*ptr));

yields the size of an array of 5 elements with the element type int.

The operator sizeof yields a value of the type size_t. So you shall rewrite the above calls of printf for example like

printf ("%zu\n" , sizeof (*ptr) );

using the conversion specifier zu instead of lu because it is not necessary that the type size_t is an alias for the type unsigned long. The C Standard allows size_t to be an alias for example for the type unsigned long long though in most systems it is indeed an alias for the type unsigned long

You could declare a pointer to an incomplete array type like

int (*ptr) [];

As it was pointed out above in any case the pointer is a complete type. So you may write

printf ("%zu\n" , sizeof (ptr));

Now as the array type in this case is incomplete then for this statement

printf ("%zu\n" , sizeof (*ptr) );

the compiler will issue an error.

If an array is not a variable length array then its size is determined at the compile time.

You could declare a pointer to a variable length array. For example

#include <stdio.h>

int main( void )
{
    for ( size_t i = 1, n = 10; i < n; i++ )
    { 
        int (*ptr) [i];
        printf ("%zu\n" , sizeof (ptr));
        printf ("%zu\n" , sizeof (*ptr));
    }
}

In this case the call of printf that output the size of the pointer will print the same value. The value of the pointer is not being changed though the types of arrays pointed to by the pointer is being changed in each iteration of the for loop and the outputted sizes of arrays will depend on the current value if the variable i and evaluate at run-time. Try yourself the demonstration program.

Bear in mind that the size of an array is calculated as the number of elements in the array multiplied by the size of its element (the size of element type).

0
arfneto On

I am using 64 bit system. When I run this code in gcc compiler it generate output 8 and 20 . My question is how many byte going to allocate for this point to an array ? It is 8 or 20 and why?

Well, first thing to consider is that ptr is static. There is no allocation except for the obvious one in the code generation: 8 bytes for a pointer in a 64-bit machine. ptr is a pointer, and points to an area the size of 5 int. The compiler will tell you that ptr is int(*)[5]. It is just a pointer to a 20-byte area in a 4-byte int machine. And points to nothing.

So the title of the question is not what we have in code: there is no memory allocation.

In the code here is not much to see:

#include <stdio.h>
int main()
{
 int (*ptr) [5];
 printf ("%lu\n" , sizeof (ptr));
 printf ("%lu\n" , sizeof (*ptr));
}

But consider

#include <stdio.h>
int main(void)
{
    int(*ptr)[5]   = NULL;
    int  x[5]      = {1, 2, 3, 4, 5};
    ptr            = x;

    printf(
        "\n\
    sizeof ptr       %3zd\n\
    sizeof (*ptr)    %3zd\n\
    sizeof (int[5])  %3zd\n\n    ",
        sizeof ptr, sizeof(*ptr), sizeof(int[5]));

    for (size_t i = 0; i < 5; i += 1)
        printf("%4d ", (*ptr)[i]);
    printf("\n    ");

    x[4]      = 42;  // change last in array
    (*ptr)[0] = 17;  // change 1st using 'ptr'

    for (size_t i = 0; i < 5; i += 1)
        printf("%4d ", (*ptr)[i]);
    printf("\n\n");

    char message[] = "Stack Overflow 1234";
    printf("Message: %s\n", message);
    ptr       = message;
    (*ptr)[4] = 0x00636261;  // change end of string
    printf("Message: %s\n", message);

    return 0;
}

That shows


    sizeof ptr         8
    sizeof (*ptr)     20
    sizeof (int[5])   20

       1    2    3    4    5
      17    2    3    4   42

Message: Stack Overflow 1234
Message: Stack Overflow 1abc

And maybe things are a bit clearer:

  • The line ptr = x; makes ptr point to the array x
  • The line ptr = message; makes ptr point to the char[] array. And (*ptr)[4] = 0x00636261; changes the last 4 bytes of the string to "abc".

All this is the effect of the parenthesis in the declaration of ptr as int (*ptr)[5].

In this code

#include <stdio.h>
int main(void)
{
  int* ptr[5];
  int  x[5]   = {1, 2, 3, 4, 5};
  ptr[0]      = x + 4;
  ptr[1]      = x + 2;
  ptr[2]      = x + 1;
  ptr[3]      = x + 3;
  ptr[4]      = x;

  printf(
      "\n\
  sizeof ptr       %3zd\n\
  sizeof (*ptr)    %3zd\n\
  sizeof (int[5])  %3zd\n\n    ",
      sizeof ptr, sizeof(*ptr), sizeof(int[5]));

  for (size_t i = 0; i < 5; i += 1)
      printf("%4d ", *ptr[i]);
  printf("\n    ");

  return 0;
}

we have no parenthesis and it shows


    sizeof ptr        40
    sizeof (*ptr)      8
    sizeof (int[5])   20

       5    3    2    4    1

We see the normal stuff: an array of 5 pointers to int and such