Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign to array in struct in c

Tags:

arrays

c

gcc

struct

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.

like image 574
Nir Avatar asked Jan 22 '14 20:01

Nir


2 Answers

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

like image 199
Eric Postpischil Avatar answered Nov 01 '22 05:11

Eric Postpischil


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

like image 22
Basile Starynkevitch Avatar answered Nov 01 '22 04:11

Basile Starynkevitch