Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't a defined, fix-sized array be assigned using a compound literal?

Why is it so that a struct can be assigned after defining it using a compound literal (case b) in sample code), while an array cannot (case c))?

I understand that case a) does not work as at that point compiler has no clue of the memory layout on the rhs of the assignment. It could be a cast from any type. But going with this line, in my mind case c) is a perfectly well-defined situation.

typedef struct MyStruct {
  int a, b, c;
} MyStruct_t;

void function(void) {
  MyStruct_t st;
  int arr[3];

  // a) Invalid
  st = {.a=1, .b=2, .c=3};
  // b) Valid since C90
  st = (MyStruct_t){.a=1, .b=2, .c=3};
  // c) Invalid
  arr = (int[3]){[0]=1, [1]=2, [2]=3};
}

Edit: I am aware that I cannot assign to an array - it's how C's been designed. I could use memcpy or just assign values individually.

After reading the comments and answers below, I guess now my question breaks down to the forever-debated conundrum of why you can't assign to arrays.

What's even more puzzling as suggested by this post and M.M's comment below is that the following assignments are perfectly valid (sure, it breaks strict aliasing rules). You can just wrap an array in a struct and do some nasty casting to mimic an assignable array.

typedef struct Arr3 {
  int a[3];
} Arr3_t;

void function(void) {
  Arr3_t a; 
  int arr[3];

  a = (Arr3_t){{1, 2, 3}};
  *(Arr3_t*)arr = a;
  *(Arr3_t*)arr = (Arr3_t){{4, 5, 6}};
}

So then what's stopping developers to include a feature like this to, say C22(?)

like image 372
davidanderle Avatar asked Dec 11 '25 17:12

davidanderle


1 Answers

C does not have assignment of arrays, at all. That is, where array has any array type, array = /* something here */ is invalid regardless of the contents of "something here". Whether it's a compound literal (which you seem to have confused with designated initializer, a completely different concept) is irrelevant. array1 = array2 would be just as invalid.

As to why it's invalid, at some level that's a question of the motivations/rationale of the C language and its design and unanswerable. However, mechanically, arrays in any context except the operand of sizeof or the operand of & "decay" to pointers to their first element. So in the case of:

arr = (int[3]){[0]=1, [1]=2, [2]=3};

you are attempting to assign pointer to the first element of the compound literal array to a non-lvalue (the rvalue produced when arr decays). And of course that is nonsense.

like image 184
R.. GitHub STOP HELPING ICE Avatar answered Dec 13 '25 07:12

R.. GitHub STOP HELPING ICE