/* loes9-3.c
   Interne Darstellung eines int-Wertes ausgeben
   Mittels typedef wird erreicht, dass das Programm leicht umgestellt werden kann
   auf die unterschiedlichen int-Typen, short, int , long
   Weil die Eingabe verschiedene Umwandlungszeichen verlangt, wird zuerst immer ein
   long-int Wert eingelesen, der dann umgewandelt wird
*/

#include <stdio.h>

typedef long int t_integer;    /* hier kann der Datentyp gewaehlt werden */


/* dualprint1 und dualprint2 gibt den Wert z in der internen Darstellung aus
   dualprint1: Loesung ohne Zeiger
   dualprint2: dem Kapitel Zeiger entsprechend Loesung mit Zeigern
*/

void dualprint1( t_integer z )
{
   int size = 8 * sizeof (t_integer);  /* Anzahl der Bits                          */
   unsigned long int mask;             /* damit funktionierts bis zum Typ long int */
   int i;

   mask = 1L << size-1;                /* Wichtig! 1L ist die long int Konstante 1 */

   for (i = 0; i < size; i++) {
     if (i > 0 && i % 8 == 0) putchar(' ');
     putchar(z & mask ? '1' : '0');
     mask >>= 1;
   }
   putchar('\n');
}

/* dualprint2 ist eine sehr allgemeine Loesung. Sie funktioniert fuer
   beliebige Datentypen (z.B. auch fuer long long int, oder double)
   Die Funktion gibt einfach die naechsten n Bytes ab der Adresse p aus,
   aber in absteigender Reihenfolge von links nach rechts.
*/
void dualprint2( unsigned char *p, int n)
{
   unsigned char mask;
   int i;


   p = p + n - 1;   /* p auf oberstes Byte positionieren */
   do {
     mask = 128;    /* Bitmuster 10000000 */
     for (i = 0; i < 8; i++) {
       putchar(*p & mask ? '1' : '0');
       mask >>= 1;
     }
     putchar(' ');
     p--;
     n--;
   } while (n > 0);
   putchar('\n');

}

int main(void)
{
  t_integer z;
  long int zlong;

  do {
    printf("z = ");
    scanf("%li", &zlong);
    z = (t_integer) zlong;
    dualprint1 (z);
    dualprint2 ( (unsigned char *) &z, sizeof (t_integer));
    /*             Anfangsadresse    ,    Laenge              */
  } while (z != 0);

  return 0;
}