web-dev-qa-db-fra.com

"erreur: affectation à l'expression avec erreur de type tableau" lorsque j'affecte un champ struct (C)

Je suis un programmeur C débutant. Hier, j’ai appris à utiliser les structures C et à les appliquer à la résolution de problèmes spécifiques. Cependant, lorsque je testais mon C IDE (Codeblocks 16.01) pour apprendre cet aspect de la programmation en C, j'ai rencontré un problème étrange. Le code est le suivant:

#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;
}

Lors de la compilation, le compilateur (GCC 4.9.3-1 sous Windows) m’a signalé une erreur disant

"erreur: affectation à une expression avec erreur de type tableau"

sur instruction

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

alors que si je le fais

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

ça marche. Qu'est-ce que je fais mal?

28
Chief096

Vous faites face à un problème dans

 s1.name="Paolo";

parce que, dans le LHS, vous utilisez un type array, qui n'est pas assignable.

Pour élaborer, de C11, chapitre §6.5.16

l'opérateur d'affectation doit avoir une valeur modifiable comme opérande gauche.

et, en ce qui concerne la valeur modifiable, du chapitre §6.3.2.1

Une lvalue modifiable est une lvalue qui n'a pas de type tableau, [...]

Vous devez utiliser strcpy() pour copier dans le tableau.

Cela dit, data s1 = {"Paolo", "Rossi", 19}; fonctionne bien, car il ne s’agit pas d’un opérateur direct affectation impliquant une affectation. Nous utilisons ici un liste d'initialisation entre accolades pour fournir les valeurs initiales de objet. Cela suit la loi d'initialisation, comme mentionné dans le chapitre §7.7.9

Chaque liste d'initialiseur entre accolades est associée à un objet en cours. Lorsque aucune désignation n'est présente, les sous-objets de l'objet actuel sont initialisés dans l'ordre en fonction du type de l'objet actuel: éléments de tableau dans l'ordre croissant d'indice, membres de la structure dans l'ordre de déclaration et premier membre nommé d'une union. [... .]

40
Sourav Ghosh

Veuillez vérifier cet exemple ici: Accès aux membres de la structure

Il est expliqué que la bonne façon de le faire est la suivante:

strcpy(s1.name , "Egzona");
printf( "Name : %s\n", s1.name);
12
user5308956
typedef struct{
     char name[30];
     char surname[30];
     int age;
} data;

définit que data devrait être un bloc de mémoire de 60 caractères plus 4 pour l'int *

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

Cela alloue la mémoire sur la pile.

data s1;

Les devoirs ne font que copier des chiffres, parfois des pointeurs.

Cela échoue

s1.name = "Paulo";

parce que le compilateur sait que s1.name est le début d'une structure longue de 64 octets et que "Paulo" est un caractère [] long de 6 octets (6 en raison du\0 dans les chaînes C).
Par conséquent, essayez d’affecter un pointeur à une chaîne dans une chaîne.

Copier "Paulo" dans la structure au point name et "Rossi" dans la structure au point surname.

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

Vous vous retrouvez avec

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

strcpy fait la même chose mais connaît la terminaison \0 et n'a donc pas besoin de la longueur codée en dur.

Vous pouvez également définir une structure qui pointe sur des tableaux de caractères de n'importe quelle longueur.

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

Cela va créer

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

Cela fonctionnera maintenant car vous remplissez la structure avec des pointeurs.

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

Quelque chose comme ça

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

Où 4 et 10 sont des pointeurs.

* N.B. les tailles et les pointeurs peuvent être de tailles différentes, les tailles 4 ci-dessus sont 32 bits par exemple.

10
teknopaul