28. Pointer II

Pointerarithmetik

Einige wenige mathematische Operationen sind auch mit Pointern sinnvoll. Dazu gehören vor allem die Addition einer ganzen Zahl (das Ergebnis ist ein Pointer gleichen Typs) und die Subtraktion zweier Pointer (das Ergebnis ist eine ganze Zahl). Damit kann z.B. folgende Funktion zur Ermittlung der Länge eines Strings geschrieben werden:

int strlen(char *str)
{
  char *cp=str;
  while (*cp)
    cp++;
  return cp-str;
}

Pointer-Arithmetik findet immer in Einheiten des Typs, auf den der Pointer zeigt statt. In der Situation der Figur ist ap-bp==1, und ebenso cp-dp==1. Die Differenz in wirklichen Speicherzellen ist durch casten auf char* zu erhalten: (char*)ap-(char*)bp==2.

Sinn dieser Regelung ist, dass man mit Pointern ähnlich wie mit Arrays umgehen kann. In der Tat definiert der C-Standard, dass der Ausdruck a[i] für ein Array a nichts anderes als *(a+i) ist. Das wurde damals unter anderem so gemacht, weil letzteres sich einfach auf die Adressierungsarten üblicher Prozessoren abbilden lässt, und so Arrayzugriffe schnell werden.

Vielleicht fanden Kernighan and Ritichie es auch nur lustig, dass auf diese Weise ein Statement wie printf("%c[n", 3["abcd"]); nicht nur legal ist, sondern auch noch ein d ausgibt. Hacker tendieren zu etwas verschrobenem Humor.

Beispiel für die Verwendung von Pointern:

void printBigrams(char *str)
{
  char *lead=str+1, *trail=str;

  while (*trail && *lead) {
    printf("%c%c/", *trail++, *lead++);
  }
  printf("\n");
}

Aufruf z.B.:

int main(void)
{
  printBigrams("Gallia est omnis divisa in"
    "partes tres");
  return 0;
}

Ausgabe:

Ga/al/ll/li/ia/a / e/es/st/t / o/om/mn/ne/es/
s / d/di/iv/vi/is/sa/a / i/in/n / p/pa/ar/rt/
te/es/ s / t/tr/re/es/

Das ist so natürlich nicht sehr sinnvoll, könnte aber z.B. beim Erzeugen von Sprachmodellen (vgl. Folie “Arrays II”) nützlich sein.


Markus Demleitner

Copyright Notice