If you want to have an array of a size that is not known at compile time, you are correct to want to allocate the memory dynamically.
In this case, you would actually use a pointer instead of an array. Although pointers and arrays are not actually exactly the same in c, for simple use they act in a very similar way.
Stdlib is needed for malloc
#include <stdlib.h>
It would also be good for a case like this to create a struct to make handling a group of colors simpler (assuming your colors are 1 byte values, so we are using char - if they could be greater than 255, you will need to use a bigger type:
typedef struct color_t {
unsigned char r;
unsigned char g;
unsigned char b;
} color;
Then you can allocate the memory as follows:
int n = 200; //However many there are, you will need to know this before allocating memory
color* colors = (color*) malloc(sizeof(color)*n);
Malloc will reserve as many bytes as you ask it for, and return a pointer to the start of the memory. So, you use sizeof() to get the size in bytes of the color structure, and then multiply that by the amount of values you need.
You can then address the structure in memory using
int i = 20; //Where i is the particular color you want to access
colors[i].r = 0;
colors[i].g = 0;
colors[i].b = 0;
When you are done with the memory, you need to free it using
free(colors);
If you don't do this, the program will continue using this memory even if you no longer have the actual colors variable - for example, if it only existed inside a function.
If you did it without a struct, allocating would look like this:
unsigned char* colors = (unsigned char*) malloc(sizeof(unsigned char)*n*3);
And then accessing would look like this, as you would be skipping through 3 variables in memory each time:
colors[i*3] = 0;
colors[i*3+1] = 0;
colors[i*3+2] = 0;