“fout: toewijzing aan expressie met arraytypefout” wanneer ik een structveld (C) toewijs

Ik ben een beginnende C-programmeur, gisteren leerde ik het gebruik van C-structs en de mogelijke toepassing hiervan voor het oplossen van specifieke problemen. Toen ik echter aan het experimenteren was met mijn C IDE (Codeblocks 16.01) om dit aspect van C-programmeren te leren, kwam ik een vreemd probleem tegen. De code is de volgende:

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

Tijdens de compilatie meldde de compiler (GCC 4.9.3-1 onder Windows) me een fout die zegt

“fout: toewijzing aan expressie met arraytypefout”

op instructie

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

terwijl als ik dat doe

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

het werkt.
Wat doe ik verkeerd?


Antwoord 1, autoriteit 100%

U ondervindt een probleem in

s1.name="Paolo";

omdat u in de LHS een array-type gebruikt, dat niet toewijsbaaris.

Om uit te werken, uit C11, hoofdstuk §6.5.16

toewijzingsoperator heeft een aanpasbare waarde als linker operand.

en, met betrekking tot de aanpasbare waarde, uit hoofdstuk §6.3.2.1

Een aanpasbare lwaarde is een lwaarde die
heeft geen arraytype, […]

Je moet strcpy()gebruiken om te kopiëren naarde array.

Dat gezegd hebbende, data s1 = {"Paolo", "Rossi", 19};werkt prima, omdat dit geen directe toewijzingis met een toewijzingsoperator. Daar gebruiken we een initialisatielijst met accoladesom de beginwaarden van het objectop te geven. Dat volgt de wet van initialisatie, zoals vermeld in hoofdstuk §6.7.9

Elke door accolades ingesloten initialisatielijst heeft een bijbehorend huidig object. Wanneer nee
aanduidingen zijn aanwezig, subobjecten van het huidige object worden geïnitialiseerd in volgorde volgens
naar het type van het huidige object: array-elementen in oplopende subscriptvolgorde, structuur
leden in volgorde van aangifte, en het eerstgenoemde lid van een vakbond.[….]


Antwoord 2, autoriteit 51%

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

definieert dat dataeen geheugenblok moet zijn waarin 60 tekens plus 4 voor de int passen (zie opmerking)

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

Dit wijst het geheugen op de stapel toe.

data s1;

Opdrachten kopieert alleen getallen, soms wijzers.

Dit mislukt

s1.name = "Paulo";

omdat de compiler weet dat s1.namehet begin is van een struct van 64 bytes lang, en "Paulo"een char[] 6 bytes lang is (6 omdat van de afsluitende \0 in C-strings)
Dus proberen een aanwijzer toe te wijzen aan een string in een string.

Om “Paulo” inde struct te kopiëren op het punt nameen “Rossi” inde struct op het punt surname.

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

Je eindigt met

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

strcpydoet hetzelfde, maar het is op de hoogte van \0-beëindiging, dus heeft de lengte niet hardcoded nodig.

Als alternatief kunt u een struct definiëren die verwijst naarchar-arrays van elke lengte.

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

Hierdoor ontstaat

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

Dit werkt nu omdat je de struct vult met pointers.

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

Zoiets

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

Waar 4 en 10 wijzers zijn.

Opmerking: de ints en pointers kunnen verschillende maten hebben, de maten 4 hierboven zijn 32bit als voorbeeld.


Antwoord 3, autoriteit 23%

Bekijk dit voorbeeld hier: Toegang tot structuurleden

Er wordt uitgelegd dat de juiste manier om het te doen als volgt is:

strcpy(s1.name , "Egzona");
printf( "Name : %s\n", s1.name);

Other episodes