How to create an array without declaring the size in C?

You don't declare an array without a size, instead you declare a pointer to a number of records.

so, if you wanted to do

int bills[];

The proper way to do this in C is

int* bills;

And you will have to allocate the size at some point in time and initialize the array.

bills = (int*)malloc(sizeof(int)*items);

The same goes for arrays of other data types. If you don't know the size of the array until runtime, you should use pointers to memory that are allocated to the correct size at runtime.


You could use a combination of malloc() (or calloc()), realloc() and free() to achieve this.

Memory can be allocated as blocks of a fixed size rather than reallocating memory for each number to be stored.

Let's define a macro (or a const if you like) BLOCK_SIZE.

#define BLOCK_SIZE 10

First declare a pointer of appropriate type and allocate the first block.

Note that malloc() as well as realloc() return NULL if some error occurred due to reasons like insufficient memory.

int *ptr=malloc(sizeof(int)*BLOCK_SIZE);    
if(ptr==NULL)
{
    perror("some error");
    return 1;
}

Now declare a variable to store the maximum possible index as per the currently allocated memory (to avoid illegal memory access).

int max_index = BLOCK_SIZE-1;

Now use a loop.

for(int i=0; ; ++i)
{
    if(i > max_index)
    {
        ptr=realloc(ptr, (max_index+1 + BLOCK_SIZE)*sizeof(int));
        if(ptr == NULL)
        {
            perror("insufficient memory!");
            break;
        }
        printf("\nRealloced!");
        max_index += BLOCK_SIZE;
    }
    scanf("%d", &ptr[i]);
    printf("\n%d: %d", i, ptr[i]);
}

In each iteration, we check if i is greater than max_index. If it is, another block is allocated using realloc() before reading the value.

Don't forget to deallocate the memory once you are done using it.

free(ptr);

Also, as discussed in this post, malloc() is effectively the same as realloc() with the latter's first argument NULL.

And in the code you posted, there's no need to explicitly cast the return value of calloc() as what's returned is a void pointer which would implicitly be converted to the target pointer type.

See this and this.


C does not support arrays with a dynamic number of elements. The number of elements of an array must be determined either at compile time or since C99 can be evaluated at runtime at the point of creation. Once the array is created, its size is fixed and cannot be changed. There are a few cases where the size is not explicitly specified between the [], either in array definitions or in array declarations.

You can define an array without an explicit size for the leftmost dimension if you provide an initializer. The compiler will infer the size from the initializer:

int a[] = { 1, 2, 3 };              // equivalent to int a[3] = { 1, 2, 3 };
int m[][2] = {{ 1, 2 }, { 3, 4 }};  // equivalent to int m[2][2] = {{ 1, 2 }, { 3, 4 }};
char s[] = "Hello world\n";         // equivalent to char s[13] = "Hello world\n";

Note how the compiler adds the implicit null terminator in the string case.

You can declare an array without a size specifier for the leftmost dimension in multiples cases:

  • as a global variable with extern class storage (the array is defined elsewhere),
  • as a function parameter: int main(int argc, char *argv[]). In this case the size specified for the leftmost dimension is ignored anyway.
  • as the last member of a struct with more than one named member. This is a C99 extension called a flexible array.

The compiler has no information on the actual size of these arrays. The programmer will use some other information to determine the length, either from a separate variable or from the array contents.

In the case of a function argument, the array is passed as a pointer and even if the number of elements is specified, sizeof(argv) evaluates to the size of a pointer.

Tags:

C

Arrays

Size