Was sollte ein C-Programmierer wissen? [geschlossen]

11

Welche Konzepte / Techniken / Sprachfunktionen sollte jeder anständige C-Programmierer kennen / kennen (ausgenommen allgemeine Softwareentwicklung und ähnliches und sich nur auf C-spezifische Dinge konzentrieren). Ich würde gerne wissen, damit ich einige mögliche Lücken in meinem C-Wissen schließen kann.

Anto
quelle
9
Beginnen Sie mit den C-Fragen von Stack Overflow und prüfen Sie, ob Sie etwas nicht wissen.
Chrisaycock
3
AC-Programmierer sollte das wahrscheinlich wissen2 + 2 = 4
Edward Strange
21
Sie sollten von einem Geschäft wissen, das kugelsichere Schuhe verkauft.
Adam Crossland
1
Es gibt Hunderte von Büchern zu diesem Thema. Ihre Frage ist wirklich ziemlich vage. Sie müssen spezifischer sein, um anständige Antworten zu erhalten, die nicht nur eine Liste von Dingen sind. Und wenn ich sehe, dass die Antworten so weit von dieser Frage entfernt sind, würde ich denken, dass sie überarbeitet oder geschlossen werden muss.
Walter
2
Eine andere Programmiersprache?
Muhammad Alkarouri

Antworten:

19

Spezifisch für C? Abgesehen von Standardkonstrukten, die den meisten prozeduralen Sprachen gemeinsam sind, muss ich sagen:

  • (ab) Verwenden des Präprozessors
  • Linker vs Compiler
  • Zeiger Zeiger Zeiger!
  • Wie Arrays Zeiger sind, sind Arrays
  • Wie C-Strings funktionieren und wie sie auch Zeiger und Arrays sind
  • Wie schlecht die Verwendung von C-Strings zu Pufferüberläufen führen kann
  • Wie man irgendetwas in irgendetwas verwandelt (es sind immerhin nur 1s und 0s :))
  • Manuelle Speicherverwaltung malloc / free
  • Stapel gegen Haufen
  • Zeiger-Aliasing (warum es in C99 illegal ist)
  • Denken Sie an die Entwicklung in Form von Modulen (.h / .c-Dateien) mit einer Reihe öffentlich verfügbarer Funktionen anstelle von strengen Klassen
  • Gewerkschaften
  • Warum Sprintf dir den Fuß abblasen kann
  • Funktionszeiger
Doug T.
quelle
Ich würde der Liste "Pufferüberläufe" hinzufügen.
Aidan Cully
@ Aidan, guter Fang. Hinzugefügt.
Doug T.
2
Wie C-Arrays und Zeiger nicht gleich sind: books.google.ca/…
Matthieu
Zeiger sollten mindestens dreimal mehr wiederholt worden sein
Gaurav
8

Verstehen Sie Zeiger und Sie werden Computer verstehen.

PP.
quelle
12
Nein, Sie werden einfach die Illusion bekommen, dass Sie Computer verstehen.
Job
4

Neben der hervorragenden Antwort von Pythonagras

wie man komplizierte Erklärungen schreibt (oder zumindest liest), wie z char (*(*funcs[4])())[10]

funcs ist ein Array [4] von Zeigern auf eine Funktion, die einen Zeiger auf das Array [10] von char zurückgibt

tcrosley
quelle
1
Wenn es so komplex wird, gehört das vielleicht in einen Kommentar?
Job
7
Vielleicht sollte er lernen, wie man es vermeidet, so zu schreiben?
FabianB
3
  1. Ganzzahlige Beförderungsregeln
  2. Initialisieren Sie alles auf einen bekannten Wert
  3. GOTO ist nicht böse, besonders wenn es zur Behandlung von Ausnahmen / Fehlern verwendet wird
  4. malloc und / oder calloc können NULL zurückgeben ... stellen Sie sicher, dass Ihre Prüfung Rückgabewerte liefert
  5. Häufige kleine Speicherzuordnungen können zu einer Fragmentierung des Heapspeichers führen.
  6. Zeigerarithmetik
  7. Bitmasken sind dein Freund
  8. x >> 1 entspricht x / 2 für vorzeichenlose Ganzzahlen
Pemdas
quelle
+1 für GOTO nicht böse sein :)
zvrba
2

AC-Programmierer sollten ... andere Sprachen kennen! ;-) Es ist immer fruchtbar, Konzepte aus anderen Sprachen verschiedener Paradigmen zu kennen, wie OOP, funktionale Programmierung und so weiter.

Im Ernst, ein Blick auf den verschleierten Programmierwettbewerb macht Spaß und ist seltsamerweise auch eine gute Erfahrung.

PhiLho
quelle
2

Ich erwähnte "Pufferüberläufe" in einem Kommentar zu Pythagras 'Antwort. Ich sollte wahrscheinlich klarstellen, was ich ein bisschen meinte. In C reicht es nicht aus zu wissen, dass die direkte Arbeit mit dem Speicher gefährlich ist - Sie sollten auch genau verstehen, wie gefährlich dies ist. Ich mag die Metapher "Sich in den Fuß schießen" für all diese Fälle nicht wirklich - oft ist es nicht so, dass Sie den Abzug betätigen, aber oft ist es ein Schauspieler mit Interessen, die Ihren und / oder den Ihrer Benutzer widersprechen .

Wenn Sie beispielsweise in einer Architektur mit absteigendem Stapel (die gängigsten Architekturen passen zu dieser Rechnung - x86 und ARM im Allgemeinen enthalten), wenn Sie eine Funktion aufrufen, wird die Rücksprungadresse für die Funktion nach den in der Liste definierten lokalen Variablen auf dem Stapel abgelegt Körper der Funktion. Wenn Sie also einen Puffer als lokale Variable deklarieren und diese Variable der Außenwelt aussetzen, ohne auf Pufferüberlauf zu prüfen, gehen Sie wie folgt vor:

void myFn(void) {
    char buf[256];
    gets(buf);
}

Ein externer Benutzer kann Ihnen eine Zeichenfolge senden, die die Rücksprungadresse vom Stapel überschreibt. Grundsätzlich kann er die Laufzeitidee Ihres Programms für das Aufrufdiagramm ändern, das zur aktuellen Funktion führt. Der Benutzer gibt Ihnen also eine Zeichenfolge, die die binäre Darstellung eines ausführbaren Codes für Ihre Architektur darstellt, genügend Auffüllungen, um den Stapel zu überlaufen myFn, und einige zusätzliche Daten, um die Rücksprungadresse zu überschreiben myFn, um auf den Code zu verweisen, den er Ihnen gegeben hat. Wenn dies passiert, myFnverzweigt es normalerweise zu Code, den der böswillige Benutzer bereitgestellt hat , wenn er normalerweise die Kontrolle an seinen Anrufer zurückgegeben hätte. Wenn Sie C- (oder C ++) Code schreiben, der möglicherweise nicht vertrauenswürdigen Benutzern ausgesetzt ist, müssen Sie diesen Angriffsvektor verstehen. Sie sollten verstehen, warum ein Pufferüberlauf gegen den Stapel oft (aber nicht immer) leichter ausgenutzt werden kann als einer gegen den Heap, und Sie sollten verstehen, wie der Speicher im Heap aufgebaut ist (nicht unbedingt zu detailliert, aber der Die Vorstellung, dass eine malloc()Region von Kontrollstrukturen umgeben ist, kann helfen, zu verstehen, warum Ihr Programm in einer anderen malloc()oder in einer anderen abstürzt free().

C macht Sie mit einfachen Details über die Funktionsweise Ihres Computers vertraut und bietet Ihnen eine direktere Kontrolle über Ihren Computer als jede andere vom Benutzer bearbeitete Sprache, die heute weit verbreitet ist. Mit großer Leistung geht eine große Verantwortung einher - Sie müssen diese Details auf niedriger Ebene verstehen, um sicher und effektiv mit C arbeiten zu können.

Aidan Cully
quelle
0

Zusätzlich zu den anderen guten Antworten möchte ich der Liste defensive Programmiertechniken hinzufügen .

Verwenden Sie beispielsweise Asserts am Anfang / Ende von Funktionen, um den Vertrag zu überprüfen.

AndersK
quelle