Can you define the size of an array at runtime in C
Asked Answered
C

10

8

New to C, thanks a lot for help.

Is it possible to define an array in C without either specifying its size or initializing it.

For example, can I prompt a user to enter numbers and store them in an int array ? I won't know how many numbers they will enter beforehand.

The only way I can think of now is to define a max size, which is not an ideal solution...

Comply answered 20/10, 2009 at 1:20 Comment(0)
M
15

Well, you can dynamically allocate the size:

#include <stdio.h>

int main(int argc, char *argv[])
{
  int *array;
  int cnt;
  int i;

  /* In the real world, you should do a lot more error checking than this */
  printf("enter the amount\n");
  scanf("%d", &cnt);

  array = malloc(cnt * sizeof(int));

  /* do stuff with it */
  for(i=0; i < cnt; i++)
    array[i] = 10*i;

  for(i=0; i < cnt; i++)
    printf("array[%d] = %d\n", i, array[i]);

  free(array);

  return 0;
}
Messina answered 20/10, 2009 at 1:24 Comment(5)
Granted, you need to know hoy many numbers you're adding on each run. realloc otherwise.Starry
thanks for the help. I guess I did not ask the question clearly in my first post. The problem is we don't know how many numbers the user will enter and the user does not know either. Say we ask the user to enter any number of numbers and we calculate average for him. All he needs to do is type number, hit enter, type another number...and type Q when he is done. How do I hold those numbers in an array without asking the user telling me how many numbers he plans to type? This will be a simple vector usage in C++ ...Comply
sorry, average is a bad example, since all we need is sum, let's say we need to hold all the numbers to do some fancy calculation ...Comply
@Bobby - Speaking of typos, "dynamically" has no "o" in it. But that's not a serious issue.Apteral
In C++, the "vector" class is dynamically reallocating your memory when it grows beyond the size. In C, there is no built-in mechanism to do this; you either need to implement it yourself (using realloc) or use a third-party library that implements vectors or linked lists in C.Necaise
C
6

Perhaps something like this:

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

/* An arbitrary starting size. 
   Should be close to what you expect to use, but not really that important */
#define INIT_ARRAY_SIZE 8

int array_size = INIT_ARRAY_SIZE;
int array_index = 0;
array = malloc(array_size * sizeof(int));

void array_push(int value) {
  array[array_index] = value;
  array_index++;
  if(array_index >= array_size) {
    array_size *= 2;
    array = realloc(array, array_size * sizeof(int));
  }
}

int main(int argc, char *argv[]) {
  int shouldBreak = 0;
  int val;
  while (!shouldBreak) {
    scanf("%d", &val);
    shouldBreak = (val == 0);
    array_push(val);
  }
}

This will prompt for numbers and store them in a array, as you asked. It will terminated when passed given a 0.

You create an accessor function array_push for adding to your array, you call realloc from with this function when you run out space. You double the amount of allocated space each time. At most you'll allocate double the memory you need, at worst you will call realloc log n times, where is n is final intended array size.

You may also want to check for failure after calling malloc and realloc. I have not done this above.

Computer answered 20/10, 2009 at 1:58 Comment(2)
In another comment, you mentioned you wanted the program to stop asking for numbers when the user supplies a 'q'. Do this by calling scanf with %s instead of %d. Then you compare the character to 'q' and decide whether or not to quit. Then you need to convert it to int by calling atoiComputer
thanks a lot, this is clever and showed me a different way of thinking about this problem: does not have to be exact, approximate first then expand later. I will probably look into how vector is implemented in C++, which I think will offer some insights into this kind of problem.Comply
C
4

Yes, absolutely. C99 introduced the VLA or Variable Length Array. Some simple code would be like such:

#include <stdio.h>

int main (void) {

    int arraysize;
    printf("How bid do you want your array to be?\n");
    scanf("%d",&arraysize);
    int ar[arraysize];  
    return 0;
}
Computer answered 15/2, 2012 at 20:20 Comment(1)
Code block := indent with four spaces. A shortcut is: highlight block and press CTL-k. HTH.Brufsky
S
3

Arrays, by definition, are fixed-size memory structures. You want a vector. Since Standard C doesn't define vectors, you could try looking for a library, or hand-rolling your own.

You need to do dynamic allocation: You want a pointer to a memory address of yet-unkown size. Read up on malloc and realloc.

Starry answered 20/10, 2009 at 1:25 Comment(2)
Also, just to add to this, one popular method for doing a realloc() is that whenever you get need to realloc (because you ran out of room) double the size of the array; that way you are doing as few realloc calls as possible.Messina
Doubling the size at each reallocation is not about minimizing the number of realloc calls, per se, but about maintaining good asymptotic efficiency. If you add a constant increment to the vector at each reallocation, pushing in n elements takes O(n^2) time. If you multiply the size by some factor >1 each at reallocation, each push takes amortized constant time, and the whole process takes O(n) time.Caudle
H
2

If all you need is a data structure where in you can change its size dynamically then the best option you can go for is a linked list. You can add data to the list dynamically allocating memory for it and this would be much easier!!

Handset answered 20/10, 2009 at 5:1 Comment(1)
+1, A simple linked list sounds like the best option given the information in the question. If OP could clarify what he's going to do with the info after reading it in we may be able to suggest an even more appropriate data structure.Brandenbrandenburg
T
1

If you're a beginner, maybe you don't want to deal with malloc and free yet. So if you're using GCC, you can allocate variable size arrays on the stack, just specifying the size as an expression.

For example:

#include <stdio.h>
void dyn_array(const unsigned int n) {
        int array[n];
        int i;

        for(i=0; i<n;i++) {
                array[i]=i*i;
        }
        for(i=0; i<n;i++) {
                printf("%d\n",array[i]);
        }
}
int main(int argc, char **argv) {
        dyn_array(argc);
        return 0;
}

But keep in mind that this is a non standard extension, so you shouldn't count on it if portability matters.

Tile answered 10/12, 2009 at 19:0 Comment(1)
This is not a "non-standard expression" - by the time the answer had been written, this had been the international standard for 10 years. The problem are the many truly non-standard compilers from such incompetent companies such as Microsoft that do not even support 10-year-old standards.Creditable
T
0

You can use malloc to allocate memory dynamically (i.e. the size is not known until runtime).

C is a low level language: you have to manually free up the memory after it's used; if you don't, your program will suffer from memory leaks.

UPDATE

Just read your comment on another answer.

You're asking for an array with a dynamically-changing-size.

Well, C has no language/syntactic facilities to do that; you either have to implement this yourself or use a library that has already implemented it.

See this question: Is there an auto-resizing array/dynamic array implementation for C that comes with glibc?

Trypsin answered 20/10, 2009 at 2:4 Comment(0)
V
0

For something like this, you might want to look into data structures such as: Linked Lists (Ideal for this situation) Various Trees (Binary Trees, Heaps, etc) Stacks & Queues

But as for instantiating a variable sized array, this isn't really possible.

The closest to a dynamic array is by using malloc and it's associated commands (delete, realloc, etc).

But in this situation, using commands like malloc may result in the need to expand the array, an expensive operation where you initialize another array and then copy the old array into that. Lists, and other datatypes, are generally much better at resizing.

Veator answered 20/10, 2009 at 2:34 Comment(0)
P
0

If you're looking for array facilities and don't want to roll your own, try the following:

  1. Glib
  2. Apache APR
  3. NSPR
Profile answered 20/10, 2009 at 2:35 Comment(0)
R
0

Above given answers are correct but there is one correction, the function malloc() reserve a block of memory of specified size and return a pointer of type void* which can be casted into pointer of any form. Syntax: ptr = (cast-type*) malloc(byte-size)

#include<stdio.h>
#include<cstdlib>
int main(int argc,char* argv[]){
int *arraySize,length;
scanf("%d",&length);
arraySize = (int*)malloc(length*sizeof(int));
for(int i=0;i<length;i++)
    arraySize[i] = i*2;
for(int i=0;i<length;i++)
    printf("arrayAt[%d]=%d\n",i,arraySize[i]);
free(arraySize);
}
Ribera answered 4/1, 2018 at 19:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.