Fragen und Antworten zum C-Kurs
Re: Fragen und Antworten zum C-Kurs
Sorry, ich hinke etwas hinterher aber jetzt ist ja Wochenende ich bemühe mich aufzuholen.
Du schreibst das jede Anweisung mit einem ; beendet wird.
Mehrere Anweisungen umschließt man mit { }.
Jetzt frage ich mich ob C das innerhalb der Klammern als eine Anweisung sieht und warum dann nach der "Klammer zu" kein Semikolon steht.
Ach ja, ich habe heute nochmal HelloGFX gestartet, da ist tatsächlich ein Punkt mitten im Kreis, das war gar kein Staubkorn
Du schreibst das jede Anweisung mit einem ; beendet wird.
Mehrere Anweisungen umschließt man mit { }.
Jetzt frage ich mich ob C das innerhalb der Klammern als eine Anweisung sieht und warum dann nach der "Klammer zu" kein Semikolon steht.
Ach ja, ich habe heute nochmal HelloGFX gestartet, da ist tatsächlich ein Punkt mitten im Kreis, das war gar kein Staubkorn
Re: Fragen und Antworten zum C-Kurs
So, prim.c läuft ebenfalls.
Dabei hatte ich meinen ersten Tippfehler - Printf statt printf
und windows teilte mir mit das es sich nicht in der lage sieht prim.com auszuführen
ich darf anscheinend nicht *a + 4 = 42; schreiben. Der Compiler meckert das 4 kein LValue sei. Wie müsste ich das schreiben damit 4 ein LValue ist?
Dabei hatte ich meinen ersten Tippfehler - Printf statt printf
und windows teilte mir mit das es sich nicht in der lage sieht prim.com auszuführen
ich darf anscheinend nicht *a + 4 = 42; schreiben. Der Compiler meckert das 4 kein LValue sei. Wie müsste ich das schreiben damit 4 ein LValue ist?
Re: Fragen und Antworten zum C-Kurs
Moin Bernd,
die Assembler-Codesequenzen sind ein sehr interessanter Einblick in die Art wie die Compiler den C-Code umsetzen. Wenn ich die beiden Assembler-Ergebnisse einmal genauer betrachte, dann erscheint mir das Ergebnis, welches der sccz80 produziert, näher an den Vorgaben des C-Codes zu sein, ganz im Gegensatz zum zsdcc. Der sccz80 legt den Zeiger auf den Ausgabetext auf den Stack, gibt den Text aus und räumt anschließend durch pop bc den gesicherten Zeiger wieder ab. Dann gibt es ein LD hl,0 für das RETURN 0, ganz wie es im C-code steht. Der zsdcc lädt nach dem call _printf anscheinend ein Flag von _printf ins CPU Statusregister - eine Optimierung ?. Wie's dann weitergeht, ist wegen der Endlosschleife leider nicht zu sehen, aber diese Vorgehensweise wirkt auf mich wie ein unsauberes Vorgehen. So gesehen, würde ich mich eher für den sccz80 als Compiler entscheiden.
Aus rein verständnisstechnischer Sicht, würde ich trotzdem die 'while (true) {....} Schleife bevorzugen, Je früher ersichtlich wird, was beabsichtigt ist, umso besser. C hat ohnehin einen gewissen Hang zum 'Abküfi' ... ('Abküfi' => Abkürzungsfimmel)
Off-Topic: Ich versuche mich mit den Beispielen, wenn möglich, auf drei Systemen: PC, Multicomp und die Joyce. Aber jedesmal, wenn die Joyce dran ist, habe ich das Gefühl, mir sitzt Prinz Walium gegenüber. Geht es nur mir oder Euch auch so ? Wie hat man das 'Damals' nur ausgehalten. Da scheint sich doch eine Zeitenwende abgespielt zu haben...
die Assembler-Codesequenzen sind ein sehr interessanter Einblick in die Art wie die Compiler den C-Code umsetzen. Wenn ich die beiden Assembler-Ergebnisse einmal genauer betrachte, dann erscheint mir das Ergebnis, welches der sccz80 produziert, näher an den Vorgaben des C-Codes zu sein, ganz im Gegensatz zum zsdcc. Der sccz80 legt den Zeiger auf den Ausgabetext auf den Stack, gibt den Text aus und räumt anschließend durch pop bc den gesicherten Zeiger wieder ab. Dann gibt es ein LD hl,0 für das RETURN 0, ganz wie es im C-code steht. Der zsdcc lädt nach dem call _printf anscheinend ein Flag von _printf ins CPU Statusregister - eine Optimierung ?. Wie's dann weitergeht, ist wegen der Endlosschleife leider nicht zu sehen, aber diese Vorgehensweise wirkt auf mich wie ein unsauberes Vorgehen. So gesehen, würde ich mich eher für den sccz80 als Compiler entscheiden.
Aus rein verständnisstechnischer Sicht, würde ich trotzdem die 'while (true) {....} Schleife bevorzugen, Je früher ersichtlich wird, was beabsichtigt ist, umso besser. C hat ohnehin einen gewissen Hang zum 'Abküfi' ... ('Abküfi' => Abkürzungsfimmel)
Off-Topic: Ich versuche mich mit den Beispielen, wenn möglich, auf drei Systemen: PC, Multicomp und die Joyce. Aber jedesmal, wenn die Joyce dran ist, habe ich das Gefühl, mir sitzt Prinz Walium gegenüber. Geht es nur mir oder Euch auch so ? Wie hat man das 'Damals' nur ausgehalten. Da scheint sich doch eine Zeitenwende abgespielt zu haben...
Re: Fragen und Antworten zum C-Kurs
>>Wie müsste ich das schreiben damit 4 ein LValue ist?
Das was Du vrsuchst ist Pointer-Arithmetik, das muß dem Compiler aber klar gemacht werden, sonst versteht er es falsch. Versuch einmal soetwas, müßte gehen: *(&a + 4) = 42;. '&a' greift auf den Inhalt von a zu, addiert 4 hinzu und benutzt das Ergebnis dann, um 42 auf die Stelle zu schreiben, auf die *a zeigt. Das ist genau das, was ich an C so liebe.
Das was Du vrsuchst ist Pointer-Arithmetik, das muß dem Compiler aber klar gemacht werden, sonst versteht er es falsch. Versuch einmal soetwas, müßte gehen: *(&a + 4) = 42;. '&a' greift auf den Inhalt von a zu, addiert 4 hinzu und benutzt das Ergebnis dann, um 42 auf die Stelle zu schreiben, auf die *a zeigt. Das ist genau das, was ich an C so liebe.
Re: Fragen und Antworten zum C-Kurs
Ich wollte auf die Adresse a +4, also a[2] zugreifen, also *(a+2) aber ohne die Klammer.
Ginge eventuell
Ich würde es selbst ausprobieren aber ich versuche gerade die Scharniere meines Notebooks zu "reparieren"
Ginge eventuell
Code: Alles auswählen
a += 4;
*a = 42;
a -=4;
Ich würde es selbst ausprobieren aber ich versuche gerade die Scharniere meines Notebooks zu "reparieren"
Zuletzt geändert von Paul am 25.02.2023, 12:56, insgesamt 3-mal geändert.
Re: Fragen und Antworten zum C-Kurs
Davon abgesehen, darf ich mir etwas wünschen?
Ich möchte in einem der nächsten Beispiele gerne
aus Basic
wissen wie es in C aussieht
Schönes Wochenende
Ich möchte in einem der nächsten Beispiele gerne
aus Basic
Code: Alles auswählen
10 PRINT AT(10,14);"O";
Schönes Wochenende
Re: Fragen und Antworten zum C-Kurs
Zur Pointerarithmetik:
Wenn du auf ein einzelnes Byte zugreifen möchtest, dann solltest du einen char Pointer verwenden. Sagen wir mal, du hast schon einen int Pointer bzw. einen int Array a, wie im Beispiel in 10.2. Dann könntest du folgendes machen:
char *cp;
cp = (char *) a;
*(cp + 4) = 42;
Oder - ohne separate Pointer-Variable:
*( (char *) a + 4) = 42;
Man nennt das type casting; das hatten wir noch nicht...
Sagen wir, a liegt an der Speicheradresse 3000 und der Array ist mit Nullen initialisiert. Dann sieht das im Speicher so aus:
a[0] - 3000: 0 0
a[1] - 3002: 0 0
a[2] - 3004: 0 0
a[3] - 3006: 0 0
a[4] - 3008: 0 0
( (char *) a + 4) ist dann 3004, durch *( (char *) a + 4) = 42; änderst du das erste Byte des dritten int-Werts, also des int-Werts mit dem Index 2. Das ist das LSB (least significant byte), weil der Z80 int-Werte im little endian Format verarbeitet. Ein printf("%d", a[2]); liefert dann 42, denn das MSB (most significant Byte) ist 0.
a[0] - 3000: 0 0
a[1] - 3002: 0 0
a[2] - 3004: 42 0
a[3] - 3006: 0 0
a[4] - 3008: 0 0
Wenn du auf ein einzelnes Byte zugreifen möchtest, dann solltest du einen char Pointer verwenden. Sagen wir mal, du hast schon einen int Pointer bzw. einen int Array a, wie im Beispiel in 10.2. Dann könntest du folgendes machen:
char *cp;
cp = (char *) a;
*(cp + 4) = 42;
Oder - ohne separate Pointer-Variable:
*( (char *) a + 4) = 42;
Man nennt das type casting; das hatten wir noch nicht...
Sagen wir, a liegt an der Speicheradresse 3000 und der Array ist mit Nullen initialisiert. Dann sieht das im Speicher so aus:
a[0] - 3000: 0 0
a[1] - 3002: 0 0
a[2] - 3004: 0 0
a[3] - 3006: 0 0
a[4] - 3008: 0 0
( (char *) a + 4) ist dann 3004, durch *( (char *) a + 4) = 42; änderst du das erste Byte des dritten int-Werts, also des int-Werts mit dem Index 2. Das ist das LSB (least significant byte), weil der Z80 int-Werte im little endian Format verarbeitet. Ein printf("%d", a[2]); liefert dann 42, denn das MSB (most significant Byte) ist 0.
a[0] - 3000: 0 0
a[1] - 3002: 0 0
a[2] - 3004: 42 0
a[3] - 3006: 0 0
a[4] - 3008: 0 0
Re: Fragen und Antworten zum C-Kurs
Vielen Dank!
Re: Fragen und Antworten zum C-Kurs
Das würde man in C ähnlich wie in TurboPascal mit gotoxy(10, 14); machen - normalerweise...Paul hat geschrieben: ↑25.02.2023, 12:51 Davon abgesehen, darf ich mir etwas wünschen?
Ich möchte in einem der nächsten Beispiele gerne
aus Basicwissen wie es in C aussiehtCode: Alles auswählen
10 PRINT AT(10,14);"O";
Schönes Wochenende
In der Theorie muss man dazu conio.h einbinden:
Code: Alles auswählen
#include <stdio.h>
#include <conio.h>
int main(void) {
gotoxy(10, 14);
putchar('O'); // oder printf("%s", "O");
}
Code: Alles auswählen
#include <stdio.h>
void gotoXY(unsigned int x, unsigned int y) {
putchar(27); // ESC
putchar('Y'); // cursor to position
putchar(y + 32); // row + 32
putchar(x + 32); // column + 32
}
int main(void) {
gotoXY(10, 14);
putchar('O'); // oder printf("%s", "O");
}
Re: Fragen und Antworten zum C-Kurs
Nein, a ist ja schon ein Pointer; &a ist die Adresse der Pointer-Variablen, das ist ein Schritt zu weit zurück. *(a + 4) = 42; wäre richtig, wenn a ein char-Pointer wäre. Weil's aber ein int-Pointer ist, müssen wir dem C-Compiler sagen, dass er a wie einen char-Pointer behandeln soll - via type cast:
*( (char *)a + 4) = 42;
- (char *)a wandelt den int-Pointer in einen char-Pointer um.
- + 4 addiert 4 zur Speicheradresse dazu (jetzt wirklich 4 Bytes und nicht 4 int-Werte respektive 8 Bytes)
- *(...) dereferenziert den Pointer, d.h. wir kommen von der Adresse zum darunter gespeicherten Wert. Das ist ein einzelnes Byte, weil wir ja einen char-Pointer dereferenzieren.
- = 42 speichert den Wert 42 als einzelnes Byte an der neu berechneten Speicheradresse