Declaring and initializing arrays in C

前端 未结 8 2083
北海茫月
北海茫月 2020-12-01 03:15

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..         


        
相关标签:
8条回答
  • 2020-12-01 03:50

    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)}
    
    0 讨论(0)
  • 2020-12-01 03:53

    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???

    0 讨论(0)
  • 2020-12-01 04:02

    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 :-).

    0 讨论(0)
  • 2020-12-01 04:03

    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;
    }
    
    0 讨论(0)
  • 2020-12-01 04:06

    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.

    0 讨论(0)
  • 2020-12-01 04:11

    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.

    0 讨论(0)
提交回复
热议问题