Problem mit "schreiben" in Struct
-
Dann ist deine C-Referenz eine C++-Referenz (wo es das malloc auch gibt, auch wenn man es dort nie benutzt) oder will aus anderen Gründen zu C++ kompatibel sein*. In C braucht man diesen Cast nicht (wegen der anderen Regeln für Konvertierungen zwischen Pointertypen). Das einzige Argument für den Cast ist, dass man dann den C-Code auch mit einem C++-Compiler übersetzen kann. Was man ohnehin nicht tun sollte. Er ist zwar nicht direkt falsch, kann aber ein paar Probleme verursachen und zu sehr schwer zu findenden Fehlern führen. Meine Empfehlung: Weglassen.
*: Da die ersten Treffer bei Google allesamt zu C++-Referenzen führen, nehme ich mal an, dass ersteres der Fall ist. Das ist auch ok, diese Referenzen zu benutzen. Die versuchen in der Regel im Teil der C-Bibliothek auch kompatibel zu C zu bleiben und dort keine C++-Sprachmittel zu verwenden. Aber natürlich sind die Beispiele immer noch in erster Linie für C++ gedacht, was dann eben manchmal zu subtilen Unterschieden wie diesem hier führt. Es sind eben doch verschiedene Sprachen, auch wenn sie wegen des Namens und der Geschichte oft zusammen geworfen werden.
-
Guten morgen Ihr zwei
Also, ich hab mir jetzt von K&R C the Programming Languga 2nd Edition und von einem Herrn Schellong "Moderne C Programmierung - Kompendium & Referenz " besorgt.
Ich denke mal das diese beiden Bücher mir doch weiterhelfen sollten.Nochmals habe ich jedoch eine Frage zu den "Referenzen".
Wie Sepp schon festgestellt hat, war das gestern aus der C++Refernce . My fault.Also gehen wirs mal an :
wenn ich eine selbsterstellte Funktion habe, z.B.:
void set_axis(struct E6Pos *pt, int *status, int *turn)
so muss, ich beim Aufruf wie folgt übergeben : (habs probiert, anders gehts auch nicht)
bla bla set_axis(&Home_Pos, &act_status, &act_trun)
wobei Home_Pos ne Struct vom Typ E6Pos ist.
Also da check ich das mit dem Adressoperator.
So, jetzt aus der Referenz: (fgets)
char *fgets(char *s, int n, FILE *stream)
Hier funktioniert das ganze , z.B. so:
char Data[80] fgets(Data, sizeof(Data), stdin);
Hier brauch ich keine Adressoperator...why? Weil Data festgelegt ist?
hingegen bei folgender Funktion (fwrite)
size_t fwrite(const void *buffer, size_t groesse, size_t anzahl, FILE *stream)
habe ich folgendes Beispiel angesehen :
int main(void) { FILE *stream; long list[NUM]; /*NUM ist als 100 definiert int numwritten; stream = fopen("myfile.dat", "w+b"); /* assign values to list[] */ numwritten = fwrite(list, sizeof(long), NUM, stream); printf("Number of items successfully written : %d\n", numwritten); return 0;
Ok... list ist klar, size of ist klar, NUM?? Naja dazu komme ich noch, stream ist auch klar.
Jetzt ein Beispiel aus dem (mittlerweile auch von mir) verhassten Buch : (Galileo...)
struct { char name[20]; char vornam[20]; char wohnort[30]; int alter; int plz; char Strasse[30]; } adressen; FILE *quelle; strcpy(adressen.name, "Barack"); strcpy(adressen.vornam, "Obama"); strcpy(adressen.wohnort, "Washington D.C"); adressen.alter = 55; adressen.plz = 23223; ... if((quelle=fopen("adres.dat", "w+b")) == NULL) ... fwrite(&adressen, sizeof(struct adressen), 1, quelle);
??? Wieso braucht er jetzt den Adressoperator? bei dem sizeof das "struct" nimmt er im nachfolgenden Beispiel nicht mehr her. Aber warum die 1? Bei dem andren Beispiel wurde NUM angegeben (da war das ganze ein Array, mit 100 longs) ... Also vermute ich 1.) Beispiel hat 100 Long einträge mit der größe von long geschrieben, und das Galileo Beispiel will nur einmal die Struct schreiben. OK
Aber wie zum Teufel ist jetzt so ne Referenz zu lesen?
Bei einer selbsterstellen funktion die nen Pointer in der Parameterliste enthält brauch ich zum zu weisen den "&".
Wenn ich mir jetzt die Referenz so ansehe... und dann die Beispiele.... Ich habs auf probiert, für die Struct gings mit dem "&". Wahh...
-
Deine Lernweise ist (untertrieben gesagt) unkoordiniert.
Du hangelst dich von einer grundlegenden Fragestellung zur nächsten, z.Z. scheint fwrite dein Problem.
Außerdem zitierst du falschen, uncompilierbaren Code, nämlichstruct { ... } adressen;
ist eine Definition einer Variablen,
dann ist aber
sizeof( struct adressen )
unmöglich.
Der Adressoperator & ist ein Synonym für "Adresse auf", und ist nur für Variablen (mit Name, Typ, Speicherbereich und Wert) gültig, also nicht für Typen.
Der operator sizeof ist auch für Typen erlaubt.
-
Lies im K&R das Kapitel Pointers and Arrays (5.3 bei mir).
Da wird die "Ähnlichkeit" von Zeigern und Arrays erklärt, die
char *fgets(char*, int, FILE*); void f(void){ char Data[80] fgets(Data, sizeof(Data), stdin); }
zugrundeliegt.
-
Dieser Code stammt nicht von mir sondern ist 1 zu 1 aus dem GalileoBuch!!
Das da was nicht stimmt dachte ich mir schon.
Hier der Link :
http://openbook.galileocomputing.de/c_von_a_bis_z/016_c_ein_ausgabe_funktionen_017.htm#mj72d8bcd5c9fd159c248b24caf558e345Unter Bockweise schreiben mit fwrite Abb 16.7
Nein, ich hangle mich auch nicht, ich habe schon erfolgreich mit fwrite geschrieben und seit ich die Diskussion gestern angestossen habe, bzw. meine Frageorgie , ist mir rückwirkend doch etwas unklar.
fwrite war nur ein Beispiel für das Lesen der C Refernzen, das mir Kopfzerbrechen bereitet.
-
DirkB schrieb:
Arrays verhalten sich in C auch anderes als normale Variablen.
Und gerade das Verständnis vom Zusammenspiel von Zeigern und Arrays ist für die Stringverarbeitung in C enorm wichtig.
Das Verständnis hast du z.Zt nicht. Darum auch deine Fehler.
Im K&R gibt es extra ein Kapitel über
Zeiger und Vektoren
(Arrays)Der Name eines Array (also ohne die []) steht schon für die Adresse des ersten Elements vom Array. Das ist gleichbedeutend mit
&Data[0]
Bei fwrite steht der erste Parameter für die Adresse, von wo aus die Daten geschrieben werdeb sollen.
Der zweite gibt die Größe eines Elements an,
der dritte die Anzahl der Elemente und
der vierte den Stream, über den die Ausgabe erfolgen soll.Beim ersten Beispiel schreibst du 100 long Werte (darum sizeof(long), 100)
Beim zweiten Beispiel schreibst du eine ganze Struct
-
Falls du dich fragst, warum bei
fwrite
zwei Paramter für die Anzahl angegeben werden, man kann ja schließlich auchsize*count
rechnen (wie bei malloc).Dann schau dir mal den Rückgabewert von
fwrite
an. Der gibt die Anzahl der erfolgreich gelesenen Elemente an (und nicht Byte).
-
DirkB schrieb:
Der Name eines Array (also ohne die []) steht schon für die Adresse des ersten Elements vom Array. Das ist gleichbedeutend mit
&Data[0]
.
.
Beim ersten Beispiel schreibst du 100 long Werte (darum sizeof(long), 100)
Beim zweiten Beispiel schreibst du eine ganze StructDarum für die Struct das "&" oder? Weil der Structname allein nicht wie bei dem Array die Adresse des ersten Members enthält?
-
structs sind keine Arrays!
Du kannst structs einander zuweisen und auch als Rückgabewert einer Funktion nutzen.
struct foo barbar(void); ... struct foo bar1, bar2; bar1 = barbar(); bar2 = bar1;
Das geht mit Arrays nicht!
-
schon klar das eine struct kein array ist .
Darum für die Struct das "&" oder? Weil der Structname allein nicht wie bei dem Array die Adresse des ersten Members enthält
Es ging nur um das & .
Kennt jmd. noch ein gutes Refernz buch in Druckversion?
-
Django2012 schrieb:
Kennt jmd. noch ein gutes Refernz buch in Druckversion?
"C in a nutshell" - O'Reilly
ist, glaube ich, die umfassendste C-Referenz (auch C99).
http://www.amazon.de/C-Nutshell-In-OReilly/dp/0596006977
Gibt's auch als PDF im Internet, mir ist aber die gedruckte Version lieber.
-
Besten Dank allerseits!
Was ich noch aus einem anderen Beitrag entdeckt habe , und wirklich auch nicht schlecht ist :