-1

How can I let the user choose a number say n and then create an array with the size of n?

Can I just say int a[]=malloc (n*sizeof(int))?

alk
  • 69,737
  • 10
  • 105
  • 255
zoids3
  • 65
  • 10
  • 1
    I'd be careful letting users allocate an arry of any size. Unless they are trusted i.e you. A huge allocation could have stabilty issues – phil Nov 29 '18 at 07:08

5 Answers5

3

There are two ways to do that. If the array size is small then you can use variable length array

/* Valid in C99 and later */
int n;
scanf("%d", &n);
int a[n];  

This will allocate memory on stack. Other way is you can use dynamic memory allocation which will allocate memory on the heap

 int *a = malloc(n*sizeof(int));  
haccks
  • 104,019
  • 25
  • 176
  • 264
  • what do you consider a small array size? – fbynite Nov 29 '18 at 08:06
  • @fbynite; Because generally stack has limited size and the memory for VLAs are allocated on stack. – haccks Nov 29 '18 at 08:41
  • yea, that's what I'm wondering about, the size. What's the size boundary where you say, this array might be in excess of X amount of bytes and it should be allocated on the heap instead? – fbynite Nov 29 '18 at 08:53
  • Can't say much about it. It's OS job to allocate a fixed size memory for stack and it is completely platform specific. You can use `ulimit -s` or `ulimit -a` to check the stack size on your system. On my system `ulimit -s` shows `8192` kbytes. – haccks Nov 29 '18 at 09:25
  • 1
    VLAs are C since C99 only and optional since C11. In C++ they do not exist at all. – alk Nov 29 '18 at 11:49
  • @alk; But question is tagged only C. – haccks Nov 29 '18 at 11:58
  • 2
    Yes, sure. My comment was not meant as criticism, but as addition only. – alk Nov 29 '18 at 12:00
  • @alk; Didn't took it as criticism :) Edited the answer. – haccks Nov 29 '18 at 12:13
2

Yes if u want to set the size of the array at run-time.

Then u should go for dynamic memory allocation(malloc/calloc).

int a[]=malloc (n*sizeof(int));//this not possible.
int *a =malloc (n*sizeof(int)); // this is possible.
2

Your idea is nearly correct:

int a[] = malloc(n*sizeof(int));

Using malloc is the correct way. But you cannot assign the returned address to an array.

You must use a pointer variable instead:

int *a = malloc(n*sizeof(int));
Gerhardh
  • 11,688
  • 4
  • 17
  • 39
2

There are two basic ways for allocating the memory to create an array where the size to the array is determined as input:

The first one is, allocating the memory for array in the 'stack' segment of memory where the size of array is taken as input ant then the array of that particular size is defined and granted memory accordingly.

int n;
scanf("%d",&n);            //scanning the size
int arr[n];                //declaring the array of that particular size here

The second one is, allocating the required memory in the 'heap' segment of memory.It is the memory allocated during runtime (execution of the program) So,another way of declaring an array where size is defined by user is

int n,*arr;
scanf("%d",&n);
arr=malloc(n*sizeof(int));        //malloc function provides a contiguous space 

or

arr=calloc(n,sizeof(int));      //calloc function is similar,initializes as 0

to use both these functions make sure to include stdlib.h.

Pyder
  • 21
  • 4
0

Variable length arrays (VLAs) were added to C with C99, but made optional with C11. They are still widely supported, though. This is the simplest way to define an array with user-selected size at runtime.

Other than that VLAs may not be available on all platforms, they also may fail silently when there is an allocation failure. This is a disadvantage that malloc() avoids when used correctly.

You can't assign to an array in C, and instead you need to store the value returned by malloc() in a pointer. Note that malloc() returns NULL when there is an allocation failure, allowing code to check for failure and proceed accordingly. The actual allocation might look like this:

int *a_dyn = malloc(sizeof *a_dyn * arr_sz);

This is an idiomatic way of calling malloc(). Note that there is no need to cast the result of malloc(), and note that the operand to sizeof is not an explicit type, but rather an expression involving a_dyn. The sizeof operator uses the type of the expression *a_dyn, which is in fact int (there is no dereference made). This is less error-prone and easier to maintain when types change during the life of a program than coding with explicit types. Also note that the sizeof expression comes before arr_sz. This is a good practice to follow: sometimes you might have a call like:

int *arr = malloc(sizeof *arr * nrows * ncols);

Placing sizeof first forces the multiplication to be done using size_t values, helping to avoid overflow issues in the multiplication.

Don't forget to free any memory allocated with malloc() when it is no longer needed, avoiding memory leaks.

Whether you use a VLA or malloc(), you must validate user input before using it to avoid undefined behavior. Attempting to allocate an array of non-positive size leads to undefined behavior, and attempting to allocate too much memory will lead to an allocation failure.

Here is an example program that illustrates all of this:

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

#define ARR_MAX  1024                 // some sensible maximum array size

int main(void)
{
    int arr_sz;
    int ret_val;
    /* validate user input */
    do {
        printf("Enter array size: ");
        ret_val = scanf("%d", &arr_sz);
    } while (ret_val != 1 || arr_sz < 1 || arr_sz > ARR_MAX);

    /* use a VLA */
    int a_vla[arr_sz];
    for (int i = 0; i < arr_sz; i++) {
        a_vla[i] = i;
        printf("%d ", a_vla[i]);
    }
    putchar('\n');

    /* use malloc() */
    int *a_dyn = malloc(sizeof *a_dyn * arr_sz);
    if (a_dyn == NULL) {                                 // malloc failure?
        fprintf(stderr, "Unable to allocate memory\n");
    } else {                                             // malloc success
        for (int i = 0; i < arr_sz; i++) {
            a_dyn[i] = i;
            printf("%d ", a_dyn[i]);
        }
        putchar('\n');
    }

    /* avoid memory leaks */
    free(a_dyn);

    return 0;
}
ad absurdum
  • 19,498
  • 5
  • 37
  • 60