views:

178

answers:

6

Is there a way to declare first and then initialize an array in C?

So far I have been initializing an array like this:

int myArray[SIZE] = {1,2,3,4....};

But I need to do something like this

int myArray[SIZE];

myArray = {1,2,3,4....};
+2  A: 

Why can't you initialize when you declare?

Which C compiler are you using? Does it support C99?

If it does support C99, you can declare the variable where you need it and initialize it when you declare it.

The only excuse I can think of for not doing that would be because you need to declare it but do an early exit before using it, so the initializer would be wasted. However, I suspect that any such code is not as cleanly organized as it should be and could be written so it was not a problem.

Jonathan Leffler
Thanks for the quick reply! I need to initialize after declaring, because will be different depending on a condition, I mean something like thisint myArray[SIZE];if(condition1) { myArray{x1, x2, x3, ...}} else if(condition2) { myArray{y1, y2, y3, ...}} ..and so on.I'm using XCode
Dave H
Are the arrays constant? If so, one possibility is to use two separate initialized constant arrays, and then set a pointer (to constant data) to point to the relevant array. You would also make the arrays static. If the arrays are not constant, then I believe you are stuck with calculating each element in turn.
Jonathan Leffler
Yes, the arrays are constant, I'll try this method too, thanks.
Dave H
+8  A: 

In C99 you can do it using a compound literal in combination with memcpy

memcpy(myarray, (int[]) { 1, 2, 3, 4 }, sizeof myarray);

(assuming that the size of the source and the size of the target is the same).

In C89/90 you can emulate that by declaring an additional "source" array

const int SOURCE[SIZE] = { 1, 2, 3, 4 }; /* maybe `static`? */
int myArray[SIZE];
...
memcpy(myarray, SOURCE, sizeof myarray);
AndreyT
I would say *definitely* `static`.
caf
I think the most convenient way in my case, instead of assigning each element, copy each desired array to a global array.Thank you very much
Dave H
+1 for C99. ;)memcpy(myarray,(int [sizeof(myarray)/sizeof(myarray[0])]{1,2,3,4},sizeof myarray);to init the rest to appropriate zero.
Nyan
@Nyan: Great idea. This will also trigger an error if there are too many initializers.
AndreyT
@AndreyT: I've posted an addendum to your answer which will also trigger a compile-time error if there are too _few_ initializers.
Joseph Quinsey
A: 

Is there a way to declare first and then initialize an array in C?

There is! but not using the method you described.

You can't initialize with a comma separated list, this is only allowed in the declaration. You can however initialize with...

myArray[0] = 1;
myArray[1] = 2;
...

or

for(int i = 1; i <= SIZE; i++)
{
  myArray[i-1] = i;
}
Jacob
Thanks, but what I was looking for was being able to initialize it in a comma separated list, because those arrays will be very large and I thought that it would be more convenient that way.
Dave H
+2  A: 

No, you can't set them to arbitrary values in one statement (unless done as part of the declaration).

You can either do it with code, something like:

myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 27;
:
myArray[99] = -7;

or (if there's a formula):

for (int i = 0; i < 100; i++) myArray[i] = i + 1;

The other possibility is to keep around some templates that are set at declaration time and use them to initialise your array, something like:

static const int onceArr[]  = {  0,  1,  2,  3,  4,..., 99};
static const int twiceArr[] = {  0,  2,  4,  6,  8,...,198};
:
int myArray[7];
:
memcpy (myArray, twiceArr, sizeof (myArray));

This has the advantage of (most likely) being faster and allows you to create smaller arrays than the templates. I've used this method in situations where I have to re-initialise an array fast but to a specific state (if the state were all zeros, I would just use memset).


You can even localise it to an initialisation function:

void initMyArray (int *arr, size_t sz) {
    static const int template[] = {2, 3, 5, 7, 11, 13, 17, 19, 21, ..., 9973};
    memcpy (arr, template, sz);
}
:
int myArray[100];
initMyArray (myArray, sizeof(myArray));

The static array will (almost certainly) be created at compile time so there will be no run-time cost for that, and the memcpy should be blindingly fast, certainly faster than 1,229 assignment statements :-).

paxdiablo
A: 

Hey preet, There is no such particular way in which you can initialize the array after declaring it once.

There are three options only:

1.) initialize them in different lines :

int array[SIZE];

array[0] = 1;

array[1] = 2;

array[2] = 3;

array[3] = 4;

.

.

.

But thats not what you want i guess.

2.) Initialize them using a for or while loop:

for (i = 0; i < MAX ; i++) {

array[i] = i;

}

This is the BEST WAY by the way to achieve your goal.

3.) In case your requirement is to initialize the array in one line itself, you have to define at-least an array with initialization. And then copy it to your destination array, but I think that there is no benefit of doing so, in that case you should define and initialize your array in one line itself.

And can I ask you why specifically you want to do so???

Kumar Alok
A: 

This is an addendum to the accepted answer by AndreyT, with Nyan's comment on mismatched array sizes. I disagree with their automatic setting of the fifth element to zero. It should likely be 5 --the number after 1,2,3,4. So I would suggest a wrapper to memcpy() to produce a compile-time error when we try to copy arrays of different sizes:

#define Memcpy(a,b) do {                    /* copy arrays */       \
    ASSERT(sizeof(a) == sizeof(b) &&        /* a static assert */   \
           sizeof(a) != sizeof((a) + 0));   /* no pointers */       \
    memcpy((a), (b), sizeof (b));           /* & unnecesary */      \
    } while (0)                             /* no return value */

This macro will generate a compile-time error if your array is of length 1. Which is perhaps a feature.

Because we are using a macro, the C99 compound literal seems to need an extra pair of parentheses:

Memcpy(myarray, ((int[]) { 1, 2, 3, 4 }));

Here ASSERT() is a 'static assert'. If you don't already have your own, I use the following on a number of platforms:

#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) /* version of ASSERT() with message */ \
    enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
Joseph Quinsey