"error: assignment to expression with array type error" when I assign a struct field (C)
Asked Answered
B

5

70

I'm a beginner C programmer, yesterday I learned the use of C structs and the possible application of these ones about the resolution of specific problems. However when I was experimenting with my C IDE (Codeblocks 16.01) in order to learn this aspect of C programming, I've encountered a strange issue. The code is the following:

#include <stdio.h>

#define N 30

typedef struct{
     char name[N];
     char surname[N];
     int age;
} data;

int main() {
     data s1;
     s1.name="Paolo";
     s1.surname = "Rossi";
     s1.age = 19;
     getchar();
     return 0;
}

During the compilation, the compiler (GCC 4.9.3-1 under Windows) reported me an error that says

"error: assignment to expression with array type error"

on instruction

s1.name="Paolo" 
s1.surname="Rossi" 

while if I do

data s1 = {"Paolo", "Rossi", 19};

it works. What am I doing wrong?

Bantamweight answered 14/5, 2016 at 10:2 Comment(3)
You've discovered one of the differences between assignment and initialization.Minorca
Can you be more specific? thanks ;)Bantamweight
You can write s1 = (const data){"Paolo", "Rossi", 19};Rattray
R
85

You are facing issue in

 s1.name="Paolo";

because, in the LHS, you're using an array type, which is not assignable.

To elaborate, from C11, chapter §6.5.16

assignment operator shall have a modifiable lvalue as its left operand.

and, regarding the modifiable lvalue, from chapter §6.3.2.1

A modifiable lvalue is an lvalue that does not have array type, [...]

You need to use strcpy() to copy into the array.

That said, data s1 = {"Paolo", "Rossi", 19}; works fine, because this is not a direct assignment involving assignment operator. There we're using a brace-enclosed initializer list to provide the initial values of the object. That follows the law of initialization, as mentioned in chapter §6.7.9

Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union.[....]

Rattish answered 14/5, 2016 at 10:12 Comment(2)
If i habe char *b = "Hello" , and if i have char c[] = "hello" , both works , if for first case i do b = "helloworld" , it works too , but for second case if i do c = "helloworld" , it does not why so ?Responsion
@SurajJain that is exactly what is explained in the answer. You cannot assign to an array.Rattish
S
54
typedef struct{
     char name[30];
     char surname[30];
     int age;
} data;

defines that data should be a block of memory that fits 60 chars plus 4 for the int (see note)

[----------------------------,------------------------------,----]
 ^ this is name              ^ this is surname              ^ this is age

This allocates the memory on the stack.

data s1;

Assignments just copies numbers, sometimes pointers.

This fails

s1.name = "Paulo";

because the compiler knows that s1.name is the start of a struct 64 bytes long, and "Paulo" is a char[] 6 bytes long (6 because of the trailing \0 in C strings)
Thus, trying to assign a pointer to a string into a string.

To copy "Paulo" into the struct at the point name and "Rossi" into the struct at point surname.

memcpy(s1.name,    "Paulo", 6);
memcpy(s1.surname, "Rossi", 6);
s1.age = 1;

You end up with

[Paulo0----------------------,Rossi0-------------------------,0001]

strcpy does the same thing but it knows about \0 termination so does not need the length hardcoded.

Alternatively you can define a struct which points to char arrays of any length.

typedef struct {
  char *name;
  char *surname;
  int age;
} data;

This will create

[----,----,----]

This will now work because you are filling the struct with pointers.

s1.name = "Paulo";
s1.surname = "Rossi";
s1.age = 1;

Something like this

[---4,--10,---1]

Where 4 and 10 are pointers.

Note: the ints and pointers can be different sizes, the sizes 4 above are 32bit as an example.

Skelly answered 31/3, 2018 at 21:56 Comment(0)
L
21

Please check this example here: Accessing Structure Members

There is explained that the right way to do it is like this:

strcpy(s1.name , "Egzona");
printf( "Name : %s\n", s1.name);
Lineolate answered 3/9, 2016 at 12:42 Comment(1)
this has an extra function call overhead(which compilers can choose to inline but generally don't), which does a loop rather than inline, and this loop isnt eliminated if the machine you're compiling on can copy the whole thing in one move, it always does at least one iteration. This seems like it cannot be solved without preprocessing the source code since C won't do it for you. char x[2] = {'h', 0}; *(char (*)[2])&x = *(char (*)[2])&x; should be significantly faster than strcpy(x, x, 2) if it was valid C.Shelving
S
0

Use strcpy() function for modifying the value. Because directly assigning value to a string is not possible in C.(Not Assignable error will show).

strcpy(s1.name, "New_Name");
Slinky answered 21/11, 2021 at 12:51 Comment(1)
This is the same solution as in this other answer.Drop
S
0

you get error because you are trying to change a constant. when we initialize a string like char sample[20]; , the sample itself is a constant pointer which means you can change the value of the thing that pointer is pointing to, but you can't change the value of the pointer itself! when you initialize char sample it is like sample as a pointer is initialized aschar* const sample; and when you try to do this:s1.name="paulo"; you are actually trying to change the strings address. in fact when you compile and run your program the string "paulo" fills part of your memory independent of s1.name. to understand better you can run the following code : #include <stdio.h> int main() { char name[20]; printf("address of sample:%d address of a random string:%d",name,"paolo"); } the output will give you two independent addresses like X and Y. X is the address of s1.name and Y is the address of paulo. you can't change X to Y since it is a constant.

Stretcher answered 12/3, 2022 at 0:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.