Declaring and initializing arrays in C
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[SI开发者_StackOverflow社区ZE];
myArray = {1,2,3,4....};
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);
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, likely faster than 1,229 assignment statements but very definitely less typing on your part :-).
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;
}
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)}
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.
The OP left out some crucial information from the question and only put it in a comment to an answer.
I need to initialize after declaring, because will be different depending on a condition, I mean something like this int myArray[SIZE]; if(condition1) { myArray{x1, x2, x3, ...} } else if(condition2) { myArray{y1, y2, y3, ...} } . . and so on...
With this in mind, all of the possible arrays will need to be stored into data somewhere anyhow, so no memcpy is needed (or desired), only a pointer and a 2d array are required.
//static global since some compilers build arrays from instruction data
//... notably not const though so they can later be modified if needed
#define SIZE 8
static int myArrays[2][SIZE] = {{0,1,2,3,4,5,6,7},{7,6,5,4,3,2,1,0}};
static inline int *init_myArray(_Bool conditional){
return myArrays[conditional];
}
// now you can use:
//int *myArray = init_myArray(1 == htons(1)); //any boolean expression
The not-inlined version gives this resulting assembly on x86_64:
init_myArray(bool):
movzx eax, dil
sal rax, 5
add rax, OFFSET FLAT:myArrays
ret
myArrays:
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5
.long 6
.long 7
.long 7
.long 6
.long 5
.long 4
.long 3
.long 2
.long 1
.long 0
For additional conditionals/arrays, just change the 2 in myArrays to the desired number and use similar logic to get a pointer to the right array.
It is not possible to assign values to an array all at once after initialization. The best alternative would be to use a loop.
for(i=0;i<N;i++)
{
array[i] = i;
}
You can hard code and assign values like --array[0] = 1
and so on.
Memcpy can also be used if you have the data stored in an array already.
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???
精彩评论