Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C, why don't we usually assign dynamically allocated arrays to (a pointer to) an array type instead of a pointer to the first element?

I am a beginner when it comes to C. Still, when an array is dynamically allocated, why is the type typically kept as a pointer to the first element in the dynamically allocated block of memory? Instead, could it be assigned to (a pointer to) an array type with a length equal to what was allocated?

I made an example program that shows the "conventional" version of just using a pointer to the first element of the array and the "array" version where it is assigned to (a pointer to) an array.

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

#define ARR_SIZE 10

int main() {

    // Option 1: Pointer to type (first element)
    // Create pointer to int for the dynamically allocated array
    // Size information stored in ARR_SIZE
    int *arr_ptr = malloc(sizeof(int) * ARR_SIZE);

    // Do something to each element
    printf("Option 1: int pointer\n");
    for(size_t i = 0; i < ARR_SIZE; i++) {
        printf("i: %zu\n", i);
        arr_ptr[i] = i;
    }


    // Option 2: Assign to (a pointer to) an array type
    // Since we assign it to (a pointer to) an array type of correct size, we embed the size information into the type
    int (*arr_ptr2)[ARR_SIZE] = malloc(sizeof(int) * ARR_SIZE);

    // Do something to each element
    printf("Option 2: assign to array pointer\n");
    // No longer need to use ARR_SIZE as the size information is stored in the array type
    for(size_t i = 0; i < sizeof(*arr_ptr2)/sizeof(int); i++) {
        printf("i: %zu\n", i);
        (*arr_ptr2)[i] = i;
    }

    // Print some size information
    printf("Size of int: %zu\n", sizeof(int)); // Prints 4
    printf("Size of *arr_ptr: %zu\n", sizeof(*arr_ptr)); // Prints 4
    printf("Size of *arr_ptr2: %zu\n", sizeof(*arr_ptr2)); // Prints 40

    // Free memory ...

    return 0;
}

This example shows that assigning to (a pointer to) an array type means the length of the array is "embedded" in the type itself, so the size of the allocated block of memory can be obtained from the variable itself without the need for a "size variable." While this may not be the best example of a benefit for assigning to an array type, I imagine there are other benefits, such as clarity that this variable is an array of elements and not a pointer to a single element.

Are there any downsides to assigning it to an array type like this? Or are the potential benefits outweighed by any benefits of just using a pointer? For example, since arrays decay into pointers anyway, could this be a cumbersome "extra step" for nothing?

Thank you for any insights and clarification you can provide!

like image 280
Dawpud Avatar asked Oct 16 '25 20:10

Dawpud


1 Answers

… when an array is dynamically allocated, why is the type typically kept as a pointer to the first element in the dynamically allocated block of memory?

  1. Notation is easier. If the type of p is pointer to element, then p[i] is element i. If the type is pointer to array, then (*p)[i] is element i. Early C was designed to be terse.

  2. Early development of C intended to use pointers in place of arrays in many circumstances. Early C dealt mostly with scalar objects, and using a pointer with array indexing (p[i]) gave an easy way to access array elements without having to add support for more complicated types and expressions to the language.

  3. We often want to use dynamically allocated memory with sizes determined at run time, such as for strings of characters read from input or from a file. Using a pointer to an array whose type is not known at compile time would require the array to have a variable-length type or an incomplete type. Variable-length types did not exist in early C, and I do not believe incomplete types were well defined, if they existed. (“Incomplete” is in the index of the second edition of Kernighan and Ritchie but not the first edition.)

like image 58
Eric Postpischil Avatar answered Oct 19 '25 10:10

Eric Postpischil