C Tutorial - Expertenthemen
C Tutorial - Expertenthemen
Hallo zusammen
Strukturen organisieren:
https://www.proggen.org/doku.php?id=c:tutorial:meta
Bin bei Arrays von Zeigern.
Das Array playField ist hier 24 Byte groß - 3 Adressen zu je 8 Byte (auf einem 64 Bit-System). An den Adressen zeigt sich, dass sich jede Spalte im Spielfeld an unterschiedlichen Stellen im Speicher befinden, zumindest nicht hintereinander. Wenn wir genau hinsehen, stellen wir auch fest, dass die Adressen bei diesem Betriebssystem (Debian Linux 2.6.35.3) hier im Freispeicher befinden (der Speicher wurde mit malloc() angefordert), statt als lokale Variable der Funktion main auf dem Stack zu liegen (die Speicherstelle ist extrem groß: Die Adressen zuvor begannen mit 7fff). Wir erkennen, dass das Betriebssystem statt der 3 Byte, die wir benötigen, gleich 32 Bytes (hexadizimal 20) anfordert.
Dieser Text den ich unterstrichen habe ist mir nicht ganz klar. Warum 32 Bytes?
Danke im voraus
Xeon
Strukturen organisieren:
https://www.proggen.org/doku.php?id=c:tutorial:meta
Bin bei Arrays von Zeigern.
Das Array playField ist hier 24 Byte groß - 3 Adressen zu je 8 Byte (auf einem 64 Bit-System). An den Adressen zeigt sich, dass sich jede Spalte im Spielfeld an unterschiedlichen Stellen im Speicher befinden, zumindest nicht hintereinander. Wenn wir genau hinsehen, stellen wir auch fest, dass die Adressen bei diesem Betriebssystem (Debian Linux 2.6.35.3) hier im Freispeicher befinden (der Speicher wurde mit malloc() angefordert), statt als lokale Variable der Funktion main auf dem Stack zu liegen (die Speicherstelle ist extrem groß: Die Adressen zuvor begannen mit 7fff). Wir erkennen, dass das Betriebssystem statt der 3 Byte, die wir benötigen, gleich 32 Bytes (hexadizimal 20) anfordert.
Dieser Text den ich unterstrichen habe ist mir nicht ganz klar. Warum 32 Bytes?
Danke im voraus
Xeon
- Xin
- nur zu Besuch hier
- Beiträge: 8859
- Registriert: Fr Jul 04, 2008 11:10 pm
- Wohnort: /home/xin
- Kontaktdaten:
Re: C Tutorial - Expertenthemen
Es müssen nicht unbedingt 32 Byte sein, das darf das OS nach belieben entscheiden. Die Anforderung ist ja, dass man 3 Byte am Stück braucht und das ist bei 32 Byte am Stück ja auch gegeben.
3 Byte ist ein sehr unpraktischer Wert, die wenn die wieder freigeben werden - wann werden das nächste mal 3 Byte benötigt? Und wie aufwendig wird es, sich solche freien Stellen im Speicher zu merken? Das kostet mehr, als es bringt. Entsprechend kann das OS hingehen und Pakete schnüren. Für kleinste Speicherblöcke kann es beispielsweise 32 Byte rausgeben. Wenn Du die 3 Byte wieder freigibst und dannach 17 Byte anforderst, bekommst Du den gleichen Speicherbereich - passt ja.
Desweiteren ist der Zugriff auf eine 64 Bit Adresse schneller als auf eine Byte-Adresse. Würde ein Pointer genau auf die Speicherzelle zeigen, die nach den 3 Byte kommt, wäre der Zugriff langsamer. Die Geschwindigkeit des Programms würde also von der Anordnung der Daten abhängig sein. Speicher ist heute sehr billig, CPU Leistung ist teuer. Also legt die Speicherverwaltung Wert darauf, dass alle herausgegebenen Speicherblöcke an einer 64-Bit angepassten Adresse liegen. Das ist bei 32-Byte-Häppchen automatisch gegeben.
3 Byte ist ein sehr unpraktischer Wert, die wenn die wieder freigeben werden - wann werden das nächste mal 3 Byte benötigt? Und wie aufwendig wird es, sich solche freien Stellen im Speicher zu merken? Das kostet mehr, als es bringt. Entsprechend kann das OS hingehen und Pakete schnüren. Für kleinste Speicherblöcke kann es beispielsweise 32 Byte rausgeben. Wenn Du die 3 Byte wieder freigibst und dannach 17 Byte anforderst, bekommst Du den gleichen Speicherbereich - passt ja.
Desweiteren ist der Zugriff auf eine 64 Bit Adresse schneller als auf eine Byte-Adresse. Würde ein Pointer genau auf die Speicherzelle zeigen, die nach den 3 Byte kommt, wäre der Zugriff langsamer. Die Geschwindigkeit des Programms würde also von der Anordnung der Daten abhängig sein. Speicher ist heute sehr billig, CPU Leistung ist teuer. Also legt die Speicherverwaltung Wert darauf, dass alle herausgegebenen Speicherblöcke an einer 64-Bit angepassten Adresse liegen. Das ist bei 32-Byte-Häppchen automatisch gegeben.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Rekursion
Hallo zusammen,
Rekursion und Optimierung:
https://www.proggen.org/doku.php?id=c:t ... :recursion
Bin bei Optimierung:
Sagen wir mal ich übergebe der Funktion den Wert 7. Was passiert bei der Funktion fibonacci_intern in dieser Zeile: return fibonacci_intern( fib-1 ) + fibonacci_intern( fib-2 ); ?
Wird zuerst fibonacci_intern( fib-1 ) und dann fibonacci_intern( fib-2 ) aufgerufen und dann addiert?
Könnte mir das jemand ausführlich erklären was da passiert?
Liebe Grüße
Xeon
Rekursion und Optimierung:
https://www.proggen.org/doku.php?id=c:t ... :recursion
Bin bei Optimierung:
Code: Alles auswählen
unsigned int fibonacci_intern( unsigned int fib )
{
if( fib <= 2 ) return 1;
return fibonacci_intern( fib-1 ) + fibonacci_intern( fib-2 );
}
unsigned int fibonacci( unsigned int fib )
{
if( fib == 0 ) return 0;
return fibonacci_intern( fib );
}
Wird zuerst fibonacci_intern( fib-1 ) und dann fibonacci_intern( fib-2 ) aufgerufen und dann addiert?
Könnte mir das jemand ausführlich erklären was da passiert?
Liebe Grüße
Xeon
- Xin
- nur zu Besuch hier
- Beiträge: 8859
- Registriert: Fr Jul 04, 2008 11:10 pm
- Wohnort: /home/xin
- Kontaktdaten:
Re: Rekursion
Sehr schöne Frage!Xeon hat geschrieben: ↑Mi Jan 15, 2020 2:36 pmBin bei Optimierung:
Sagen wir mal ich übergebe der Funktion den Wert 7. Was passiert bei der Funktion fibonacci_intern in dieser Zeile: return fibonacci_intern( fib-1 ) + fibonacci_intern( fib-2 ); ?Code: Alles auswählen
unsigned int fibonacci_intern( unsigned int fib ) { if( fib <= 2 ) return 1; return fibonacci_intern( fib-1 ) + fibonacci_intern( fib-2 ); }
Wird zuerst fibonacci_intern( fib-1 ) und dann fibonacci_intern( fib-2 ) aufgerufen und dann addiert?
Könnte mir das jemand ausführlich erklären was da passiert?
Das spielt in diesem Fall eigentlich keine Rolle, da die fibonacci_intern Funktion über keine Seiteneffekte verfügt. Würde sie Variablen außerhalb der Funktion ändern, könnte die Reihenfolge der Aufrufe wichtig sein. Hier wird aber wird nur der Rückgabewert berechnet und kein Einfluss von außen ändert etwas daran.
Die Reihenfolge hängt vom Operator ab.
Grundsätzlich ist das aber geregelt, siehe hier: Operatorprioritäten. Die Assoziativität gibt an, ob erst der linke Ausdruck (L-R) oder der rechte Ausdruck (R-L) ausgewertet wird. + als Infix-Operator (inmitten zweier Operanden) ist L-R, also erst das Linke-Argument, dann das rechte.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Re: Rekursion
Hallo Xin,
ich habe an der Funktion fibonacci_intern ein bisschen experimentiert, bin aber zu keinem logischen Ergebnis gekommen.
Beendet die zweite return Anweisung im Code die Funktion oder?
Grüße
von Xeon
ich habe an der Funktion fibonacci_intern ein bisschen experimentiert, bin aber zu keinem logischen Ergebnis gekommen.
Code: Alles auswählen
unsigned int fibonacci_intern( unsigned int fib )
{
printf("- %d - ", fib); //Codeverlauf verfolgen
if( fib <= 2 ) return 1;
return fibonacci_intern( fib-2 ) + fibonacci_intern( fib-1 );
}
Grüße
von Xeon
- Xin
- nur zu Besuch hier
- Beiträge: 8859
- Registriert: Fr Jul 04, 2008 11:10 pm
- Wohnort: /home/xin
- Kontaktdaten:
Re: Rekursion
Jede Return-Anweisung beendet die Funktion. Wird eine Return-Anweisung erreicht, werden nachfolgende Anweisungen nicht mehr ausgeführt. Das return 1 sorgt also dafür, dass das nachfolgende return nicht mehr erreicht.Xeon hat geschrieben: ↑Mi Jan 22, 2020 2:33 pmich habe an der Funktion fibonacci_intern ein bisschen experimentiert, bin aber zu keinem logischen Ergebnis gekommen.
Beendet die zweite return Anweisung im Code die Funktion oder?Code: Alles auswählen
unsigned int fibonacci_intern( unsigned int fib ) { printf("- %d - ", fib); //Codeverlauf verfolgen if( fib <= 2 ) return 1; return fibonacci_intern( fib-2 ) + fibonacci_intern( fib-1 ); }
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Re: Rekursion
Ah, jetzt habe ich verstanden für was die zweite Return-Anweisung gut ist: Wenn die Rekursion zu Ende ist wird der Rückgabe Wert von fibonacci_intern( fib-2 ) + fibonacci_intern( fib-1 ) zusammen addiert und dann wird das Ergebnis an die zweite Return-Anweisung übergeben. Richtig?
Liebe Grüße
Xeon
Liebe Grüße
Xeon
- Xin
- nur zu Besuch hier
- Beiträge: 8859
- Registriert: Fr Jul 04, 2008 11:10 pm
- Wohnort: /home/xin
- Kontaktdaten:
Re: Rekursion
Genau. Und die Summe der beiden rekursiben Aufrufe wird dann als Ergebnis an Funktion übergeben, die "mich" gerufen hat.Xeon hat geschrieben: ↑Mi Jan 22, 2020 4:42 pmAh, jetzt habe ich verstanden für was die zweite Return-Anweisung gut ist: Wenn die Rekursion zu Ende ist wird der Rückgabe Wert von fibonacci_intern( fib-2 ) + fibonacci_intern( fib-1 ) zusammen addiert und dann wird das Ergebnis an die zweite Return-Anweisung übergeben. Richtig?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Speicher mit free() freigeben
Hallo zusammen,
Software-Architektur:
https://www.proggen.org/doku.php?id=c:t ... chitecture
Hier der Quellcode von dem Thema Software-Architektur:
Es geht um diese Zeilen:
Ich habe mal in dem Buch "C von A bis Z - Das umfassende Handbuch" gelesen, dass man nur angeforderten Speicher freigeben darf. Was meint ihr dazu?
Software-Architektur:
https://www.proggen.org/doku.php?id=c:t ... chitecture
Hier der Quellcode von dem Thema Software-Architektur:
Code: Alles auswählen
void node_delete( struct Node * toDelete )
{
if( toDelete )
{
struct Parameter *tempP, *p = toDelete->Parameter;
struct Node *tempN, *n = toDelete->SubNodes;
printf( "-%s: \"%s\"\n", ( toDelete->Name ) ? "Node" : "Text",
( toDelete->Name ) ? toDelete->Name : toDelete->Text );
free( toDelete->Name ); // Falls Name vorhanden, dann löschen
free( toDelete->Text ); // Falls Text vorhanden, dann löschen
// Parameter löschen
while( p )
{
tempP = p->Next;
parameter_delete( p );
p = tempP;
}
// Unterknoten löschen
while( n )
{
tempN = n->Next;
node_delete( n ); // Rekursiver Aufruf
n = tempN;
}
// Diese Node löschen
free( toDelete );
}
}
struct Node * node_newWithLength( char const * name, unsigned int nameLength )
{
struct Node * result = malloc( sizeof( struct Node ) );
printf( "+Node: %*s\n", nameLength, name );
if( result )
{
result->Name = malloc( 1 + nameLength );
if( result )
{
memcpy( result->Name, name, nameLength );
result->Name[nameLength] = '\0';
result->Next = NULL;
result->Text = NULL;
result->Parameter = NULL;
result->SubNodes = NULL;
return result;
}
node_delete( result );
}
return NULL;
}
struct Node * node_new( char const * name )
{
return node_newWithLength( name, strlen( name ) );
}
Code: Alles auswählen
free( toDelete->Name ); // Falls Name vorhanden, dann löschen
free( toDelete->Text ); // Falls Text vorhanden, dann löschen