Assign to array in struct in c

39,679

Solution 1

The syntax something = { initial values } is allowed only in initializations, where an object is defined, such as:

long mem[1000] = { 1, 2, 3, 4, 5, 6 };

An expression such as x = value is an assignment and cannot use the syntax for initializations.

One alternative is to create a temporary object, which you initialize, and then copy the contents of that temporary object into the target:

static const long temporary[] = { 1, 2, 3, 4, 5, 6 };
memcpy(test->mem, temporary, sizeof temporary);

Regarding the edit:

Arrays may not be assigned; x = value is not valid if x is an array. However, structures may be assigned, so another alternative is to create a structure as a temporary object, initialize it, and assign it:

// (After the malloc is successful.)
static const Test temporary = { { 1, 2, 3, 4, 5, 6 } };
*test = temporary;

Note, however, that this code does something the prior code does not. The prior example I showed merely copies six elements into the array. This code creates a temporary object of type Test, which contains 1000 elements, most of them zero, and it copies all of those elements into *test. Even if the compiler optimizes this and uses some code to clear *test rather than actually copying zeroes stored in memory, it takes longer than just copying six elements. So, if you just want a few elements initialized and do not care about the rest, use the former code. If you want all the elements initialized (most to zero), you can use the latter code. (Even so, I would consider alternatives, like using calloc instead of malloc.)

Solution 2

Arrays are not pointers (but arrays decay to pointers, see this), and you cannot assign arrays (only initialize them, or assign struct-s containing them). You could copy the array, e.g.

Test *test =  (Test *)malloc(sizeof(Test)); 
if (!test) { perror("malloc"); exit(EXIT_FAILURE); };
static const int arr[] = {1,2,3,4,5,6};
memcpy (test->mem, arr, sizeof(arr));

BTW, you could copy without using memcpy by coding your loop for (int i=0; i<6; i++) test->mem[i] = arr[i]; ....

This leaves 9994 integers in test uninitialized; you might want to clear them:

memset (test->mem+6, 0, 9994*sizeof(int));

or use another for loop.

You could also define your initialized structure, e.g.

Test mystruct = {0, 2, 4, 6, 8};

then assign it, e.g.

*test = mystruct;

but you cannot assign arrays! Even

// wrong code, won't compile
int ta[4] = { 0, 1, 2, 3}; // initialization, not assignment
int tb[4] = { 2, 4, 6, 8}; // ditto
int *tp = &ta;
ta = tb; // wrong!
tb = tp; // also wrong

won't compile.

FWIW, C++11 has std::array to help about that.

The §6.5.16.1 Simple assignment section of the C11 standard (see n1570 draft page 102) lists a set of constraints regarding assignment, and array assignment don't fit there. Hence it is forbidden. A rule of thumb is that only scalars (that includes pointers and numerical l-values) or struct-s can appear on the left hand side of an assignment (or be return-ed from a function).

Share:
39,679
Nir
Author by

Nir

Updated on January 23, 2020

Comments

  • Nir
    Nir over 4 years

    I have the following code:

    typedef struct Test {
      long mem[1000];
    } Test;
    
    extern Test *test;
    int main() {
        Test *test =  (Test *)malloc(sizeof(Test)); 
        test->mem[0] = 1;
        test->mem[1] = 2;
        test->mem[2] = 3;
        test->mem[3] = 4;
        test->mem[4] = 5;
        test->mem[5] = 6;
       return 0;
    }
    

    It's working OK, but I want to change the initalization of the mem array to be in that way:

    test->mem = {1,2,3,4,5,6};
    

    But the gcc giving me this error:

    error: expected expression before '{' token test->mem = {1,2,3,4,5,6}; With arrow pointing to the left open braces.

    What it can be?

    Thanks!

    EDIT: I also try this code:

    long mem[1000] = {1,2,3,4,5,6};
        test->mem = mem;
    

    And I'm getting this error from gcc:

    error: incompatible types when assigning to type 'long int[1048576]' from type 'long int *' test->mem = mem;

    I'm not allow to use any C functions.

  • Nir
    Nir over 10 years
    Sorry, I dont understand. why test->mem[0] = 1; working and test->mem = {1,2,3,4,5,6}; doesn't?
  • Eric Postpischil
    Eric Postpischil over 10 years
    I do not see how the statement “Arrays are not pointers” is relevant. The code in the question does not attempt to use a pointer as an array or vice-versa. The problem is attempting an assignment using initialization syntax.
  • ApproachingDarknessFish
    ApproachingDarknessFish over 10 years
    @EricPostpischil I believe that it became relevant with the latest edit to the question.
  • Eric Postpischil
    Eric Postpischil over 10 years
    @ValekHalfHeart: The edit tries to assign one array to another, not to use an array as a pointer or vice-versa. The error message mentions the pointer that has been produced from the array, but that is not the OP’s intent.