2

How to assign c type array to struct member that is also an array of the same type? Here's my struct:

typedef struct {

  uint8_t type;
  uint8_t data[10];

} MyStruct;

Here's the creation of the struct:

MyStruct myStruct;

Here's generation of some array:

uint8_t generatedArray[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

Here's my assignment:

myStruct.data = generatedArray;
1
  • You can't assign it. Arrays cannot be lvalues in C. But you can copy it (memcpy()). Commented Oct 31, 2012 at 16:22

6 Answers 6

3

As other answers have stated an array is not directly assignable and you must use a function such as memcpy:

memcpy(myStruct.data, generatedArray, sizeof(myStruct.data));

However...

C is a language with a long history. Early languages had roughly the notion of "little" and "large" types, the former being directly assignable and the latter not. Some later languages made everything assignable (or for functional languages, values).

Original C had primitive types; integer, float, etc.; and arrays of these types. The former, being "little", were assignable, the latter, being "large", were not. Subsequently C gained structures, and decided these were "little"...

So, a little strangely, while you cannot directly assign one array to another you can assign on structure to another, and in particular you can assign a structure with just one field which is an array... You can also write literal structure values, including for those with array-valued fields; and being C with its "types are comments" approach you can cast a pointer to an array to a pointer to a structure...

The above means you can write "fun" code like:

typedef struct
{
    uint8_t type;
    uint8_t data[10];
} MyStruct;

typedef struct
{
    uint8_t data[10];
} MyArray;

typedef struct
{
    uint8_t type;
    MyArray array;
} MyStruct2;

void arrayAssignment(int x)
{
    MyStruct myStruct;
    MyArray generatedArray = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; // structure literal

    *(MyArray *)&myStruct.data = generatedArray;

    uint8_t generatedArray2[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; // array literal
    *(MyArray *)&myStruct.data = *(MyArray *)generatedArray2;

    MyStruct2 myStruct2;
    myStruct2.array = generatedArray; // no casts at all, but element access is myStruct2.array.data[index]
}

Note that none of the casts, indirections, etc. or in the final example the extra array. in the indexing cost anything in the compiled code - they are all simply ways to persuade the compiler to use its built-in array assignment.

Many would of course argue against regular uses of these techniques!

Sign up to request clarification or add additional context in comments.

2 Comments

And what if in MyStruct2 there was 'MyArray *array' ?
@Aerox - structure assignment copies the fields of the structure. If a field is a pointer, as in your MyArray *array, then the value of the pointer itself is copied so after the assignment the original and the copied structure values both reference the same MyArray structure via their individual array fields. Does that answer your question?
2

Arrays cannot be assigned to each other, that is, an array identifier is not allowed to be on the left side of an assignment. When on the right side, the array is said to decay to a pointer to its first element, so it doesn't really represent the whole chunk.

You should use memcpy instead, and pass the size of the array which can be obtained via the sizeof operator. For short arrays, an optimizing compiler may be able to substitute the memcpy call with more efficient instructions to exploit the target architecture better.

Comments

1

You are attempting to assign to an array, but an array cannot be assigned to. An array is, however, an lvalue:

The following object types are lvalues, but not modifiable lvalues:

  • An array type
  • An incomplete type
  • A const-qualified type
  • An object is a structure or union type and one of its members has a const-qualified type

You'll need to use memcpy instead. You ought to pass sizeof(myStruct.data) as the third argument to memcpy:

memcpy(myStruct.data, generatedArray, sizeof(myStruct.data));

Comments

0

You can't directly assign an array like that. You'll have to copy it over.

Comments

0

I wonder how your compiler let you do that assignment. You cannot use array as modifiable lvalue. Also when used as rvalue an array represents a pointer to the first element in the array. Other ways of achieving this would be to use pointers or to use memcopy()

Comments

0

With C99 you can use compound literals and string literals as initializer ( if uint8_t has the same bit-representation as char )

MyStruct myStruct={.data="\1\2\3\4\5\6\7\x8\x9\xa"};
...
MyStruct myStruct;
myStruct = (MyStruct){.data="\1\2\3\4\5\6\7\x8\x9\xa"};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.