Programmieren in C


von Prof. Dr. Rainer Thomas

8. Zeiger

8.1 Eigenschaften von Zeigern
8.2 Zeiger als Parameter und Funktionswert
8.3 Dynamische Speicherallokation
8.4 Adressarithmetik
8.5 Verwandschaft zwischen Zeigern und Arrays
8.6 Mehrdimensionale Arrays und Pointer-Arrays
8.7 Kommandozeilenparameter in C
8.8 Zeiger auf Funktionen
8.9 Near- und Far-Zeiger in TURBO/BORLAND-C


8.1 Eigenschaften von Zeigern

Zeiger (Pointer) in C


/*--------------------------------------------------------------------*/
/* Programm POINDEM1                                                  */
/*--------------------------------------------------------------------*/
/* Einfaches Demonstrationsprogramm zu Zeigern                        */
/*--------------------------------------------------------------------*/

#include <stdio.h>

void main(void)
{
  int x=1, y, *px, *py;

  px=&x;                   /* Wertzuweisung an Zeiger mittels
                              Adressoperator */

  *px=5;                   /* Modifikation des Zeigerobjekts */
  (*px)++;                 /* Klammern notwendig, wenn Zeigerobjekt */
                           /* modifiziert werden soll   */

  y=*px+1;                 /* Zeigerobjekt als Operand */

  printf("\nx = %d\n",x);
  printf("y = %d\n",y);

  py=px;                   /* Zuweisung des Werts eines anderen Zeigers */

  *py+=3;                  /* Modifikation des Zeigerobjekts */

  printf("\nWert des Zeigerobjekts von px : %d\n",*px);
  printf("Wert des Zeigerobjekts von py : %d\n",*py);
}

/*--------------------------------------------------------------------*/

Bildschirmausgabe :




/*-------------------------------------------------------------------*/
/* Programm POINDEM2                                                 */
/*-------------------------------------------------------------------*/
/* Demonstration der direkten Wertzuweisung an Zeiger                */
/* sowie des Einlesens von Zeigerwerten                              */
/*-------------------------------------------------------------------*/

#include <stdio.h>

void main(void)
{
  char x='A',y='F',*px;
  int a;

  /* --1--------- Direkte Zuweisung eines Integerwertes ------------ */
  /* - Compiler gibt Warnung aus : Different levels of indirection - */
  px=0xffd8;
  printf("\n1)  Wert des Zeigerobjekts von px : %02x\n",*px);

  /* --2--------- Zuweisung eines mittels Cast-Operator ------------ */
  /* ------------      umgewandelten Integerwertes      ------------ */
  px=(char *)0xffd8;
  printf("\n2)  Wert des Zeigerobjekts von px : %02x\n",*px);

  /* --3----- Direkte Eingabe einer Adresse als Integerwert -------- */
  printf("\n3)  Adresse (Offset)    ? ");
  scanf("%x",&px);
  printf("    Inhalt dieser Zelle : %02x\n",*px);

  /* --4-------- Mittels Cast-Operator typgewandelte als ----------- */
  /* -----------     Integerwert eingelesene Adresse     ----------- */
  printf("\n4)  Adresse (Offset)    ? ");
  scanf("%x",&a);
  px=(char *) a;
  printf("    Inhalt dieser Zelle : %02x\n",*px);

  /* --5------ Direkte Eingabe einer Adresse als Zeigerwert -------- */
  /* ---------                 (ANSI-C !!!)                 -------- */
  printf("\n5)  Adresse (Offset)    ? ");
  scanf("%p",&px);
  printf("    Inhalt dieser Zelle : %02x\n",*px);
}

Bilschirmausgabe :



/*-------------------------------------------------------------------*/
/* Programm POINDEM3                                                 */
/*-------------------------------------------------------------------*/
/* Demonstration der Ausgabe von Zeigerwerten                        */
/*-------------------------------------------------------------------*/

#include <stdio.h>

void main(void)
{
  char x='A',y='F',*ptr;
  int a;


  /* --1----- Ausgabe einer Adresse direkt als Integerwert --------- */
  /* --------               (sedezimal)                    --------- */
  /* --------------------------------------------------------------- */
  printf("\n1)  Adresse (Offset) von x : %04x\n",&x);
  ptr=&x;
  printf("    Adresse (Offset) von x : %04x\n",ptr);


  /* --2----- Ausgabe einer mittels Cast-Operator in einen --------- */
  /* -------- Integerwert (sedezimal)  gewandelten Adresse --------- */
  /* --------------------------------------------------------------- */
  printf("\n2)  Adresse (Offset) von y : %04x\n",(int)&y);
  ptr=&y;
  printf("    Adresse (Offset) von y : %04x\n",(int)ptr);


  /* --3----- Ausgabe einer Adresse direkt als Zeigerwert ---------- */
  /* --------                (ANSI-C !!!)                 ---------- */
  /* --------------------------------------------------------------- */
  printf("\n3)  Adresse (Offset) von x : %04p\n",&x);
  ptr=&x;
  printf("    Adresse (Offset) von x : %04p\n",ptr);
}

/*-------------------------------------------------------------------*/

Bildschirmausgabe :


8.2 Zeiger als Parameter und Funktionswert



8.3 Dynamische Speicherallokation

Dynamische Speicherallokation in C


Funktionen der ANSI-C-Std-Bibliothek zur dynamischen Speicherverwaltung

/* -------------------------------------------------------------------- */
/*          malloc          -      Allokation eines Speicherblocks      */
/* -------------------------------------------------------------------- */

#include <stdlib.h>                    /* enthält  Funktionsdeklaration */

void *malloc(size_t size);

/*  size    Laenge des zu allokierenden Blocks in Bytes  */

Anm:
Der Typ size_t ist der "natürliche" unsigned Typ
(u.a. in <stdlib.h> definiert)

malloc allokiert einen Speicherblock von wenigstens der Länge size Bytes (der tatsächlich allokierte Speicherblock kann infolge evtl. notwendiger Speicherplatzausrichtung größer sein)

Funktionswert :
- Pointer auf den allokierten Speicherblock, falls genügend Speicherplatz frei ist,
- bzw. NULL-Pointer, falls Speicherpl. nicht ausreicht


/* -------------------------------------------------------------------- */
/*     calloc  -  Allokation und Initialisierung eines Speicherblocks   */
/* -------------------------------------------------------------------- */

#include <stdlib.h>                    /* enthält  Funktionsdeklaration */

void *calloc(size_t nobj, size_t size);

  /*  nobj    Anz. Objekte, für die Speicherplatz allokiert werden soll */
  /*  size    Laenge eines Objekts in Bytes                             */

calloc allokiert einen Speicherblock von wenigstens der Länge nobj size Bytes (der tatsächlich allokierte Speicherblock kann infolge evtl. notwendiger Speicherplatzausrichtung größer sein) und initialisiert alle Bytes mit 0.

Funktionswert :
- Pointer auf den allokierten Speicherblock, falls genügend Speicherplatz frei ist,
- bzw. NULL-Pointer, falls freier Speicherplatz nicht ausreicht


/* -------------------------------------------------------------------- */
/*          free            -      Freigabe von Speicherplatz           */
/* -------------------------------------------------------------------- */

#include <stdlib.h>                     /* enthält Funktionsdeklaration */

void free(void *ptr);

       /* ptr       Zeiger auf allokierten Speicherblock */

free gibt den - zuvor allokierten - Speicherblock, auf den ptr zeigt, wieder frei.

Funktionswert :
keiner


Beispiel zur dynamischen Speicherallokation in C

/* ------------------------------------------------------------------- */
/* Programm MALDEM                                                     */
/* ------------------------------------------------------------------- */
/* Demonstrationsprogramm zur Verwendung der Bibliotheksfunktionen zur */
/* dynamischen Speicherverwaltung                                      */
/*                                                                     */
/* Einlesen, Sortieren und Ausgeben einer beliebigen Anzahl von        */
/* double-Werten                                                       */
/*                                                                     */
/* Die Funktionen zum Einlesen, Sortieren und Ausgaben eines Feldes    */
/* von double-Werten stehen in einem getrennt zu übersetzenden Modul   */
/* zur Verfügung                                                       */
/* ------------------------------------------------------------------- */

#include <stdio.h>
#include <stdlib.h>

#define DBL_SIZ   8              /* Länge eines Double-Wertes in Bytes */

extern void dfeld_ein(double *, unsigned);
extern void dfeld_sort(double *, unsigned);
extern void dfeld_aus(double *, unsigned);

void main(void)
{
  int anz;
  double *dfeld;

  printf("\nAnzahl der double-Werte ? ");
  scanf("%d", &anz);
  if (anz>0)
    if ((dfeld=malloc(anz*DBL_SIZ)) == NULL)
      printf("\nSpeicherplatz reicht nicht aus !\n");
    else
    { dfeld_ein(dfeld, anz);
      dfeld_sort(dfeld, anz);
      dfeld_aus(dfeld, anz);
      free(dfeld);
    }
  else
    printf("\nAnzahl muß >0 sein !\n");
}


8.4 Adressarithmetik

Zeigerarithmetik in C

Neben der Zuweisung und der Objektbildung lassen sich auf Zeiger in C die folgenden Operationen anwenden:


Beispiel zur Zeigerarithmetik und zu statisch-globalen Variablen in C

/* ------------------------------------------------------------------ */
/* Modul ALLOCMEM                                                     */
/* ------------------------------------------------------------------ */
/* Einfache Funktionen zur dynamischen Speicherverwaltung :           */
/* Allokation und Freigabe von Speicherplatz                          */
/*                                                                    */
/* Der dynamisch verwaltete Speicher steht als "privates" char-Array  */
/* (Speicherklasse static !) zur Verfügung                            */
/* Verwaltung erfolgt stack-ähnlich :                                 */
/* Freigabe der allokierten Speicherblöcke muß in umgekehrter Reihen- */
/* folge ihrer Allokation erfolgen                                    */
/* ------------------------------------------------------------------ */


#define NULLPOINT  0                 /* Null-Pointer */
#define LAENGE 4096

static char allocbuf[LAENGE];        /* verfuegbarer Speicherplatz */
static char *allocp=&allocbuf[0];    /* Zeiger auf jeweils naechste
                                        verfuegbare Speicherzelle  */


char *alloc(int n)         /* liefert Zeiger auf Bereich fuer n Zeichen */
{
  if (allocp+n <= &allocbuf[0]+LAENGE)
  { allocp+=n;                       /* Speicher vorhanden */
    return(allocp-n);
  }
  else return(NULLPOINT);            /* Speicher nicht vorhanden  */
}



void back(char *p)    /* Rueckgabe des Speicherplatzes ab der Adresse p */
{
  if (p>=&allocbuf[0] && p<&allocbuf[0]+LAENGE)
    allocp=p;
}


8.5 Verwandschaft zwischen Zeigern und Arrays

Pointer und Arrays in C


Beispiel zur Verwandschaft zwischen Zeigern und Arrays

/* -------------------------------------------------------------------- */
/*           Aequivalente Formulierungen der Funktion strcopy           */
/* -------------------------------------------------------------------- */


void strcopy(char str1[], char str2[])             /* s. Umdruck VPC623 */
{
  int i=0;
  while((str2[i]=str1[i]) != '\0')
    i++;
}


/* -------------------------------------------------------------------- */


void strcopy(char *str1, char *str2)
{
  int i=0;
  while ((str2[i]=str1[i]) != '\0')
    i++;
}


/* -------------------------------------------------------------------- */


void strcopy(char *str1, char *str2)
{
  int i=0;
  while ((*(str2+i)=*(str1+i)) != '\0')
    i++;
}


/* -------------------------------------------------------------------- */


void strcopy(char *str1, char *str2)
{
  while ((*str2=*str1)!='\0')
  { str2++;
    str1++;
  }
}


/* -------------------------------------------------------------------- */


void strcopy(char *str1, char *str2)
{
  while (*str2++=*str1++);
}



Anwendung der Verwandschaft zwischen Zeigern und Arrays in C :
Arrays variabler Länge


8.6 Mehrdimensionale Arrays und Pointer-Arrays

Mehrdimensionale Arrays und Pointer

Mehrdimensionale Arrays koennen als "Pointer auf Arrays" aufgefasst werden.

Beispiel :
char cf[3][4];   /* Definition und damit Speicherplatzreser-
                    vierung eines Arrays von 3 * 4 char-
                    Werten */
                 /* cf ist ein Pointer auf ein Array von
                    3 char-Arrays je der Laenge 4 */
        

cf+i ist ein Pointer auf das (i+1)-te Zeilen-Array (der immer auf das 1.Element dieses Arrays zeigt)

*(cf+i) = cf[i] ist das (i+1)-te Zeilen-Array, d.h. genauer ein Pointer auf das 1.Element des (i+1)-ten Zeilen-Arrays

---> (cf+i) und *(cf+i) liefern immer die gleiche Adresse

*(cf+i)+j = cf[i]+j ist ein Pointer auf das (j+1)-te Element des (i+1)-ten Zeilen-Arrays

*(*(cf+i)+j) = *(cf[i]+j)
= cf[i][j] = (*(cf+i))[j]
ist das (j+1)-te Element des (i+1)-ten Zeilen-Arrays

Parameterdeklaration mehrdimensionaler Felder:


Pointer - Arrays

Pointer-Arrays (Arrays von Pointern), die wiederum auf Arrays zeigen, sind von mehrdimensionalen Arrays zu unterscheiden, obwohl sie gleichartig verwendet werden koennen.

Beispiel :
char *pa[3];      /* Definition und damit Speicherplatzreser-
                     vierung eines Arrays von 3 Pointern, die
                     jeweils auf char-Werte zeigen */
                  /* pa ist ein Zeiger auf ein Array von
                     3 char-Pointern */

char ca1[4],      /* Definition und damit Speicherplatzreser-
     ca2[4],      /* vierung von  3 char-Arrays je der
     ca3[4];      /* Laenge 4 */

pa[0] = ca1;      /* Wertzuweisung an die char-Pointer */
pa[1] = ca2;
pa[2] = ca3;
        

pa+i ist ein Pointer auf die (i+1)-te Komponente des Pointer-Arrays pa
*(pa+i) = pa[i] ist das Array, auf das die (i+1)-te Komponente des Pointer-Arrays pa zeigt, d.h. genauer ein Pointer auf das 1.Element dieses Arrays
*(pa+i)+j = pa[i]+j ist ein Pointer auf das (j+1)-te Element des Arrays, auf das die (i+1)-te Komponente des Pointer-Arrays pa zeigt
*(*(pa+i)+j) = *(pa[i]+j)
= pa[i][j] = (*(pa+i))[j]
ist das (j+1)-te Element des Arrays, auf das die (i+1)-te Kompon. d. Point.-Arrays pa zeigt


Mehrdimensionale Arrays und Pointer-Arrays - Gegenüberstellung


Programmbeispiel zu mehrdimensionalen Arrays und Pointer-Arrays

/* ------------------------------------------------------------------- */
/* Programm POINDEM4                                                   */
/* ------------------------------------------------------------------- */
/* Demonstration von Ähnlichkeit und Unterschied mehrdimensionaler     */
/* Arrays und Pointer-Arrays                                           */
/* ------------------------------------------------------------------- */

#include <stdio.h>

char aacWochTagFeld[][11] = {"ungueltig",   "Montag",
                             "Dienstag",    "Mittwoch",
                             "Donnerstag",  "Freitag",
                             "Samstag",     "Sonntag" };

char *apcWochTagZeig[]    = {"ungueltig",   "Montag",
                             "Dienstag",   "Mittwoch",
                             "Donnerstag", "Freitag",
                             "Samstag",    "Sonntag" };
void main(void)
{ int i,j;
  char cZeichF,cZeichZ;
  int indein(int *, int *);
  while (indein(&i,&j)>=0)
  { cZeichF=aacWochTagFeld[i][j];
    cZeichZ=apcWochTagZeig[i][j];
    printf("aacWochTagFeld[%2d][%2d] = %02x\n",i,j,cZeichF);
    printf("apcWochTagZeig[%2d][%2d] = %02x\n",i,j,cZeichZ);
  }
}

int indein(int *iA, int *iB)
{ printf("\nZeile  ? ");  scanf("%d",iA);
  if (*iA<0) return (-1);
  else
  { printf("Spalte ? ");  scanf("%d",iB);
    if (*iB<0) return (-1);
    else return 1 ;
  }
}

/* ------------------------------------------------------------------- */

Bildschirmausgabe :
F:\RT\C\VORL>poindem4

Zeile  ? 0
Spalte ? 8
aacWochTagFeld[ 0][ 8] = 67
apcWochTagZeig[ 0][ 8] = 67

Zeile  ? 1
Spalte ? 7
aacWochTagFeld[ 1][ 7] = 00
apcWochTagZeig[ 1][ 7] = 44

Zeile  ? -1
        

Programmbeispiel zur Verwendung von Pointer-Arrays

/* -------------------------------------------------------------------- */
/* Programm POINDEM5                                                    */
/* -------------------------------------------------------------------- */
/* Einlesen einer unbekannten Anzahl von Zeilen (max. Anzahl 100)       */
/* Nach Abschluss der Eingabe (mit CTRL_Z) Ausgabe der Zeilen in umge-  */
/* kehrter Reihenfolge (letzte Zeile zuerst)                            */
/* -------------------------------------------------------------------- */

#include <stdio.h>
#include <stdlib.h>

#define MAXANZ  100
#define MAXLEN  136
#define WRITELN putchar('\n')

void strcopy(char *pcStr1, char *pcStr2)
{ while (*pcStr2++ = *pcStr1++);
}

int ZeilenEin(char *apcZeilFeld[], int iMax)
{ extern int GetLine(char *, int);         /* s. Umdruck V-PC-722 */
  char *pcNext, acZeile[MAXLEN];
  int iLaenge, iZeilZahl=0;
  while (((iLaenge=GetLine(acZeile,MAXLEN)) >= 0)
         && (iZeilZahl < iMax) && (pcNext=malloc(iLaenge+1)) != NULL)
  { strcopy(acZeile,pcNext);
    apcZeilFeld[iZeilZahl++]=pcNext;
  }
  return iZeilZahl;
}

void ZeilenAus(char *apcZeilFeld[], int iAnz)
{ int i;
  WRITELN;
  for (i=iAnz;i>0; )
  { printf("%s\n",apcZeilFeld[--i]);
    free(apcZeilFeld[i]);
  }
}

void main(void)
{ char *apcZeilen[MAXANZ];
  int iAnz;
  WRITELN;
  iAnz=ZeilenEin(apcZeilen,MAXANZ);
  ZeilenAus(apcZeilen,iAnz);
}
/* -------------------------------------------------------------------- */

Bildschirmausgabe :

8.7 Kommandozeilenparameter in C


Beispiel zu Kommandozeilen-Parametern

/* ------------------------------------------------------------------ */
/* Programm ECHOPAR                                                   */
/* ------------------------------------------------------------------ */
/* Ausgabe der Kommandozeilen-Parameter untereinander nach stdout     */
/* (Bildschirm)                                                       */
/* ------------------------------------------------------------------ */

#include <stdio.h>

void main(int argc, char *argv[])

              /*  argc     Anzahl der Kommandozeilen-Parameter        */
              /*  argv     Pointer-Array auf Kommandozeilen-Parameter */

{ int i;
  putchar('\n');
  for (i=1; i<argc; i++)
    printf("%s\n",argv[i]);
}
/* ------------------------------------------------------------------ */
Bildschirmausgabe :

/* ------------------------------------------------------------------ */
/* Programm ECHOPAR2                                                  */
/* ------------------------------------------------------------------ */
/* Ausgabe der Kommandozeilen-Parameter untereinander nach stdout     */
/* (Bildschirm)                                                       */
/* Verwendung des Namens argv selbst wieder als Pointer               */
/* ------------------------------------------------------------------ */

#include <stdio.h>

void main(int argc, char **argv)

              /*  argc     Anzahl der Kommandozeilen-Parameter        */
              /*  argv     Pointer auf Pointer-array                  */

{
  putchar('\n');
  while (--argc>0)
    printf("%s\n",*++argv);
}
/* ------------------------------------------------------------------ */

8.8 Zeiger auf Funktionen


Programmbeispiele zu Zeiger auf Funktionen

/* ----------------------------------------------------------------- */
/* Programm SIMPINT                                                  */
/* ----------------------------------------------------------------- */
/* Definition der Funktion "simpint",                                */
/* Integration einer beliebigen Funktion mit einem double-Parameter, */
/* die einen double-Wert liefert, nach dem Simpson-Verfahren         */
/* Beispiel zur Anwendung der Funktion                               */
/* ----------------------------------------------------------------- */

#include <stdio.h>

double simpint(double a, double b, unsigned n,
               double (*fkt)(double))
       /* a,b       Untere u. obere Integrationsgrenze    */
       /* n         Anz. Intervalle                       */
       /* fkt       Pointer auf zu integrierende Funktion */
{
  double x,usum,gsum,h,zh;
  int i;
  h=(b-a)/n;
  zh=2*h;
  for (usum=0,i=1,x=a+h; i<n; x+=zh,i+=2)
    usum=usum+(*fkt)(x);
  for (gsum=0,i=2,x=a+zh; i<n-1; x+=zh,i+=2)
    gsum=gsum+(*fkt)(x);
  return ((*fkt)(a)+(*fkt)(b)+4*usum+2*gsum)/3*h;
}

double rechteck(double x)        /* period. Rechteckfunktion    */
{                                /* Grundperiode : 0 ... 1.0    */
  double r;                      /* x = 0   )                   */
  r = x-(int)x;                  /* x = 0.5  >  rechteck = 0.5  */
  r = r <0 ? r+1.0 : r;          /* x = 1   )                   */
  if( r==0 || r==0.5)            /* x < 0.5     rechteck = 1.0  */
  return 0.5;                    /* x > 0.5     rechteck = 0    */
  else
    if (r<0.5) return 1.0;
    else return 0;
}

void main(void)
{
  double x1,x2;
  unsigned m;
  printf("\nUntere Grenze ? ");  scanf("%lf",&x1);
  printf("Obere  Grenze ? ");    scanf("%lf",&x2);
  printf("Intervallanzahl ? ");  scanf("%u",&m);
  printf("\nIntegral : %1.4f\n",simpint(x1,x2,m,rechteck));
}

Bildschirmausgabe :

/* ------------------------------------------------------------------- */
/* Programm FKZDEMO                                                    */
/* ------------------------------------------------------------------- */
/* Demonstrationsprogramm zu Funktionszeigern                          */
/* Auswahl einer Funktion über Indizierung eines Arrays von Funktions- */
/* zeigern                                                             */
/* ------------------------------------------------------------------- */

#include <stdio.h>
#define FKTZ 4

int add(int a, int b)
{ printf("Summe     : ");
  return a+b;
}

int sub(int a, int b)
{ printf("Differenz : ");
  return a-b;
}

int mul(int a, int b)
{ printf("Produkt    : ");
  return a*b;
}

int mod(int a, int b)
{ printf("Modulus    : ");
  return a%b;
}

void main(void)
{ int i;
  int x,y;
  int (*op[FKTZ])(int, int);      /* Array von Funktionszeigern */
  op[0]=add;
  op[1]=sub;
  op[2]=mul;
  op[3]=mod;
  while((printf("\nZwei int-Zahlen ? "), scanf("%d%d", &x, &y))!=EOF)
  { printf("Operation  (0 - ADD,  1 - SUB,  2 - MUL,  3 - MOD) ? ");
    scanf("%d",&i);
    printf("%d\n",(*op[i])(x,y));
  }
}

Bildschirmausgabe :

8.9 Near und Far-Zeiger in TURBO/BORLAND-C


Near- und Far-Zeiger in TURBO-C

Ein- und Ausgabe von Zeigerwerten in TURBO-C


Beispiel zur Ein- und Ausgabe von Zeigerwerten in TURBO-C

/*---------------------------------------------------------------------*/
/* Programm POINDEM6                                                   */
/*---------------------------------------------------------------------*/
/* Demonstration der Ein- und Ausgabe von Near- und Far-Zeigern in     */
/* TURBO-C                                                             */
/*---------------------------------------------------------------------*/

#include <stdio.h>

void main(void)
{ char cZx='A', cZy='B';
  char *pcZ1, near *npcZ2;
  char far *fpcZeig;

  /* -------------- Ausgabe eines Default-Zeigers -------------------- */
  printf("\nAdresse von cZx (Default-Zeiger) : %p", &cZx);

  /* ---------------- Ausgabe eines Near-Zeigers --------------------- */
  printf("\nAdresse von cZx (Near-Zeiger)    : %Np", (char near *)&cZx);

  /* ---------------- Ausgabe eines Far-Zeigers ---------------------- */
  printf("\nAdresse von cZx (Far-Zeiger)     : %Fp\n",(char far *)&cZx);


  /* -------------- Eingabe eines Default-Zeigers -------------------- */
  printf("\nAdresse (Offset)         ? ");
  scanf("%p", &pcZ1);

  /* ---------------- Eingabe eines Near-Zeigers --------------------- */
  printf("Adresse (Offset)         ? ");
  scanf("%Np", &npcZ2);

  /* ---------------- Eingabe eines Far-Zeigers ---------------------- */
  printf("Adresse (Segment:Offset) ? ");
  scanf("%Lp", &fpcZeig);


  /* -------- Ausgabe des Objekts der eingegebenen Zeiger ------------ */
  printf("\nObjekt von pcZ1    : %c", *pcZ1);
  printf("\nObjekt von npcZ2   : %c", *npcZ2);
  printf("\nObjekt von fpcZeig : %c\n", *fpcZeig);
}

/*---------------------------------------------------------------------*/

Bildschirmausgabe :

Beispiel zum direkten Speicherzugriff über Far-Zeiger in TURBO-C

/*------------------------------------------------------------------*/
/* Programm GIV2                                                    */
/*------------------------------------------------------------------*/
/* Ermittlung des Interrupt-Vektors, der zu einer INT-Nr. gehört    */
/* Auslesen des Interrupt-Vektors direkt aus der INT-Vektor-Tabelle */
/*------------------------------------------------------------------*/

#include <stdio.h>
#include <dos.h>

#define INT_SEG  0

void main(void)
{
  int int_nr;
  void far *int_vec;
  int int_nr_anfordern(void);
  void far *get_vect(unsigned);

  while ((int_nr=int_nr_anfordern()) != EOF)
  { int_vec=get_vect(int_nr);
    printf("Interrupt-Vektor         : %Fp\n",int_vec);
  }
  putchar('\n');
}

int int_nr_anfordern(void)
{
  unsigned zahl;
  printf("\nINT-Nr. (Abbruch CTRL-Z) ? ");
  if (scanf("%i", &zahl) != EOF)
    return zahl;
  else
    return EOF;
}

void far *get_vect(unsigned int_nr)
{
  void far *ivec;
  ivec=*(void far * far *)MK_FP(INT_SEG,4*int_nr);
  return ivec;
}

/*------------------------------------------------------------------*/

Bildschirmausgabe :

Turbo-C-Funktionen zum direkten Zugriff auf Speicher-Adressen

/* -------------------------------------------------------------------- */
/*       peekb     -     Lesen eines Bytes von einer Speicher-Adresse   */
/* -------------------------------------------------------------------- */

#include <dos.h>

char peekb(unsigned seg, unsigned offs);
peekb liest ein einzelnes Byte von der durch seg:offs angegebenen Speicher-Adresse.

Funktionswert :
gelesenes Byte


/* -------------------------------------------------------------------- */
/*  peek -  Lesen eines Int-Wertes (2 Bytes) von einer Speicher-Adresse */
/* -------------------------------------------------------------------- */

#include <dos.h>

int peek(unsigned seg, unsigned offs);
peek liest einene Integerwert (2 Bytes) von der durch seg:offs angegebenen Speicher-Adresse (und der nächsten Adresse).

Funktionswert :
gelesener Integerwert


/* -------------------------------------------------------------------- */
/*      pokeb    -     Schreiben eines Bytes in eine Speicher-Adresse   */
/* -------------------------------------------------------------------- */

#include <dos.h>

void pokeb(unsigned seg, unsigned offs, char wert);
pokeb schreibt das Byte mit dem Wert wert in die durch seg:offs angegebene Speicher-Adresse.

Funktionswert :
keiner


/* -------------------------------------------------------------------- */
/* poke - Schreiben eines Int-Wertes (2 Bytes) in eine Speicher-Adresse */
/* -------------------------------------------------------------------- */

#include <dos.h>

void poke(unsigned seg, unsigned offs, int wert);
poke schreibt den Integer-Wert wert in die durch seg:offs angegebene Speicher-Adresse (und in die nächste Adresse).

Funktionswert :
keiner


Turbo-C-Funktionen zum direkten Zugriff auf E/A-Adressen

/* -------------------------------------------------------------------- */
/*       inportb        -     Lesen eines Bytes von einer E/A-Adresse   */
/* -------------------------------------------------------------------- */

#include <dos.h>

unsigned char inportb(int eaadr);
inportb liest ein einzelnes Byte von der durch eaadr angegebenen E/A-Adresse.

Funktionswert :
gelesenes Byte


/* -------------------------------------------------------------------- */
/*   inport  -  Lesen eines Int-Wertes (2 Bytes) von einer E/A-Adresse  */
/* -------------------------------------------------------------------- */

#include <dos.h>

int inport(int eaadr);
inport liest einene Integerwert (2 Bytes) von der durch eaadr angegebenen E/A-Adresse (und der nächsten Adresse).

Funktionswert :
gelesener Integerwert


/* -------------------------------------------------------------------- */
/*      outportb      -     Schreiben eines Bytes in eine E/A-Adresse   */
/* -------------------------------------------------------------------- */

#include <dos.h>

void outportb(int eaadr, unsigned char wert);
outportb schreibt das Byte mit dem Wert wert in die durch eaadr angegebene E/A-Adresse.

Funktionswert :
keiner


/* -------------------------------------------------------------------- */
/*  outport - Schreiben eines Int-Wertes (2 Bytes) in eine E/A-Adresse  */
/* -------------------------------------------------------------------- */

#include <dos.h>

void outport(int eaadr, int wert);
outport schreibt den Integer-Wert wert in die durch eaadr angegebene E/A-Adresse (und in die nächste Adresse).

Funktionswert :
keiner


Beispiel für den direkten Zugriff auf E/A-Adressen in TURBO-C

/*---------------------------------------------------------------------*/
/* Programm CMRAM                                                      */
/*---------------------------------------------------------------------*/
/* Lesen aus dem CMOS-RAM eines IBM/AT                                 */
/* Beispiel für den direkten Zugriff auf E/A-Adressen in TURBO-C       */
/*---------------------------------------------------------------------*/

#include <dos.h>
#include <stdio.h>

#define CM_AR     0x70               /* CMOS-RAM - Adress-Register */
#define CM_DR     0x71               /* CMOS-RAM - Daten-Register  */
#define WRITELN   putchar('\n')
#define HEADER    "\n*** Lesen des CMOS-RAM ***\n"

void main(void)
{
  unsigned cm_adr;
  unsigned char wert;

  printf(HEADER);
  while ((printf("\nAdresse ? "),scanf("%i",&cm_adr))!=EOF)
  { outportb(CM_AR, cm_adr);
    wert=inportb(CM_DR);
    printf("Wert    : %02X\n",wert&0x0ff);
  }
  WRITELN;
}

Bildschirmausgabe :




Zum Inhaltsverzeichnis Zum nächsten Abschnitt


Copyright © FH München, FB 04, Prof. Dr. Rainer Thomas
V - PC - 811 - 00 - TH - 05
V - PC - 812 - 00 - TH - 04
V - PC - 813 - 00 - TH - 04
V - PC - 814 - 00 - TH - 03
V - PC - 821 - 00 - TH - 06
V - PC - 825 - 00 - TH - 01
V - PC - 826 - 00 - TH - 07
V - PC - 827 - 00 - TH - 02
V - PC - 831 - 00 - TH - 05
V - PC - 832 - 00 - TH - 05
V - PC - 841 - 01 - TH - 05
V - PC - 841 - 02 - TH - 05
V - PC - 842 - 01 - TH - 04
V - PC - 842 - 02 - TH - 02
V - PC - 842 - 03 - TH - 02
V - PC - 843 - 00 - TH - 01
V - PC - 844 - 00 - TH - 02
V - PC - 845 - 00 - TH - 02
V - PC - 846 - 00 - TH - 03
V - PC - 847 - 00 - TH - 05
V - PC - 848 - 00 - TH - 06
V - PC - 851 - 00 - TH - 05
V - PC - 852 - 00 - TH - 05
V - PC - 861 - 00 - TH - 04
V - PC - 863 - 00 - TH - 04
V - PC - 864 - 00 - TH - 02
V - PC - 871 - 00 - TH - 03
V - PC - 872 - 00 - TH - 01
V - PC - 873 - 00 - TH - 04
V - PC - 875 - 00 - TH - 03
V - PC - 876 - 00 - TH - 02
V - PC - 878 - 00 - TH - 04
V - PC - 879 - 00 - TH - 01