Zeiger

Aus Ethersex_Wiki
Wechseln zu: Navigation, Suche

Einleitung

Wie im ersten Teil bereits erwähnt: es gibt in C keine Strings bzw. keine String-Klasse wie evtl. von Programmiersprachen wie Java bereits bekannt :-)

Variablen

Eine normale Variable wird direkt im Arbeitsspeicher des Computers (Stackbereich) abgelegt. Wenn wir also eine Variable vom Typ int erstellen und dieser einen Wert zuweisen, wird dieser Wert einfach an der für diese Variable reservierten Stelle im Arbeitsspeicher abgelegt (analog auch für alle anderen elementaren Variablentypen).

Zeiger

Ein Zeiger ist nunmehr ein Konstrukt, das aussagt, dass an einer bestimmten Stelle im Arbeitsspeicher eine Variable abgelegt ist (der Zeiger selbst speichert sozusagen die Adresse der Variablen).

Bleistift

#include<stdio.h>
#include<string.h>

int
main(void)
{
  int lokalvar = 4;
  int *zeiger = &lokalvar;

  printf("Der Wert der Variablen ist: %d", lokalvar);
  printf("Abfrage des Wertes über Zeiger: %d", *zeiger);

  /* Wertzuweisung an den Zeiger */
  *zeiger = 5;
  printf("Der neue Wert unserer Variablen: %d", lokalvar);

  return 0;
}


  • Um einen Zeiger zu deklarieren, muss zwischen Typspezifizer und Variablenname ein * eingegeben wert (zum Beispiel int *zeiger)
  • dem Zeiger muss (ähh, sollte) eine Adresse übergeben werden, kein Wert. Um die Adresse der Variablen lokalvar zu erfahren, kann das & verwendet werden.
  • im Beispiel wird dem Zeiger zeiger die Adresse der Variablen lokalvar übergeben
  • um den vom Zeiger referenzierten Wert zu erfahren, müssen wir den Zeiger dereferenzieren - hierzu dient ebenfalls das *-Zeichen (siehe die zweite printf-Anweisung)
  • ebenso funktioniert die Wertzuweisung ...
    • um der referenzierten Variablen einen Wert zuzuweisen, muss diese ebenfalls dereferenziert werden (*zeiger = 5;)
    • wenn das Sternchen weggelassen wird, wird dem Zeiger eine neue Adresse zugewiesen!!
#include<stdio.h>
#include<string.h>

int
main(void)
{
  int var_a = 65;
  int var_b = 66;

  int *zeiger = &var_a;

  printf("Wert-A: %d, B: %d", var_a, var_b);

  *zeiger = 97;
  printf("Wert-A: %d, B: %d", var_a, var_b);

  /* hier ändern wir die Variable, auf welche                                   
   * der Zeiger verweist, nicht die Variable                                    
   * selbst (wir verwenden kein Sternchen!!)
   */
  zeiger = &var_b;
  printf("Wert-A: %d, B: %d", var_a, var_b);

  *zeiger = 98;
  printf("Wert-A: %d, B: %d", var_a, var_b);

  return 0;
}
  • sollte selbsterklärend sein :-)
  • Zeiger auf Zeiger auf Zeiger .... auf Variablen sind möglich. Die Anzahl der *-Zeichen muss nur entsprechend erhöht werden
  • ein String ist unter C nichts anderes als ein Zeiger auf eine Reihe von chars
    • char *variable = "Hallo Welt!";
    • dabei ist das letzte Zeichen der Zeichenkette ein Null-Zeichen um das Ende zu markieren (nicht das Zeichen für die Ziffer 0!)
    • "Hallo" ist ein Zeiger auf ein Reihe von 6 chars!


Zeichenfolgen manipulieren (kopieren, vergleichen, etc.pp)

strcpy (Zeichenfolgen kopieren)

#include<stdio.h>
#include<string.h>

int
main(void)
{
  const char *alt = "Hallo!";
  char neu[7];

  strcpy(neu, alt);
  printf("%s", neu);
  return 0;
}

strcmp (Zeichenfolgen vergleichen)

#include<stdio.h>
int
main(void)
{
  const char *text1 = "Hallo!";
  const char *text2 = "Hallo!";

  if(strcmp(text1, text2) == 0)
    printf("Die Zeichenfolgen sind gleich!");
  return 0;
}
  • Rückgabewerte von strcmp
    • 0 - Texte identisch
    • kleiner 0 - text1 ist vorher (alphabetisch)
    • größer 0 - text1 kommt alphabetisch später

strchr (ein Zeichen in der Zeichenkette suchen)

#include<stdio.h>
#include<string.h>

int
main(void)
{
  const char *text1 = "Vorname=Stefan";
  const char *fundstelle = 
    strchr(text1, '=');

  if(fundstelle == NULL)
    printf("nicht gefunden!");
  else
    printf("Wert: %s", fundstelle + 1);
  return 0;
}


Dateneingabe mit fgets und scanf

fgets - eine Zeile lesen

#include<stdio.h>
#include<string.h>

int
main(void)
{
  char puffer[64];
  fgets(puffer, sizeof(puffer), stdin);

  printf("Ihre Eingabe war: %s", puffer);
  return 0;
}
  • sizeof() gibt die länge der jeweiligen Variable, in diesem Fall des char-arrays zurück (also 64)
  • fgets() liest in diesem Fall maximal 63 Zeichen (beachte das null-byte!) inkl. dem eingegebenen \


Segmentation Fault und Buffer Overflow

Ein segmentation fault tritt immer dann auf, wenn ihr (auf Grund wilden hantierens mit Zeigern) Speicherbereiche ändert, die ihr nicht hättet ändern dürfen (ähm, sollen). Wenn Ihr zum Beispiel ein char-array von 5 Zeichen nehmt und "Hallo" reinschreibt, landet das abschließende NULL-Byte in einem nicht euch gehörenden Speicher...

Buffer Overflow läuft in die gleiche Richtung. Dabei wird eine Schwachstelle im angegeriffenen Programm genutzt, die zulässt, dass man gezielt Speicher überschreibt. Es wird geeigneter Programmcode geschrieben, der dann ausgeführt wird (Schadroutine) ...