Vielleicht können wir an dem gemeinsam nachvollziehen, wie das funktioniert.
Das ist nicht die einzige (und bestimmt nicht die beste) Art und Weise, wie man das implementieren kann, aber es funktioniert, und das ist erst mal die Hauptsache:
Code: Alles auswählen
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*
* Binärdump eines Strings
*/
void bitdump(const char *str)
{
char bitchar[9];
do {
char *cp = bitchar;
int i;
for (i = 7; i >= 0; i--)
{
*cp++ = ((*str >> i) & 1 ? '1' : '0');
}
*cp++ = '\0';
printf("%s ", bitchar);
} while (*str++);
}
/*
* Hexdump eines Strings
*/
void hexdump(const char *str)
{
do {
printf("%02x ", *str & 0xff);
} while (*str++);
}
/*
* Array mit Masken entsprechend der Bitpositionen
*
* ACHTUNG: in oktaler Darstellung!
*/
static const unsigned char mask[] =
{
0001, /* 00000001 */
0003, /* 00000011 */
0007, /* 00000111 */
0017, /* 00001111 */
0037, /* 00011111 */
0077, /* 00111111 */
0177, /* 01111111 */
};
bool oct2sept(char *sept, const char *oct)
{
int pos = 0; /* hält die Zeichenposition im String Modulo 8 */
do {
if (*oct & 0x80) /* Fehler: Bit 7 ist gesetzt - String nicht codierbar */
return false;
*sept = *oct >> pos; /* Zeichen kopieren und nichtgenutzte niederwertige Bits (die */
/* schon im vorigen Byte abgehandelt sind) abhängig von der */
/* Position im String wegshiften */
*sept |= (*(oct + 1) & mask[pos]) << (7 - pos); /* den "links freigewordenen" Platz mit den Bits des nächsten Zeichens auffüllen */
if (pos != 7) /* nach 7 Zeichen haben wir eins eingespart */
sept++;
pos = (pos + 1) % 8; /* Zeichenposition updaten */
} while (*oct++);
*sept = '\0';
return true;
}
int main(int argc, const char *argv[])
{
const char *octs = "Eine etwas laengere Mitteilung";
char septs[160];
(void) argc;
(void) argv;
bitdump(octs);
puts("");
if (oct2sept(septs, octs))
{
printf("\"%s\" in 7-Bit-Darstellung:\n", octs);
}
else
{
fprintf(stderr, "FEHLER: String enthält 8-Bit Zeichen - nicht codierbar\n");
exit(1);
}
bitdump(septs);
puts("");
hexdump(octs);
puts("");
hexdump(septs);
puts("");
return 0;
}
Ich habe auch mal nach PDU-Konvertierprogrammen gegockelt. Die Beispielroutinen, die man so findet, drehen die Bits in der 7-Bit Darstellung zweimal auf links. Wozu das gut sein soll, kann ich nur raten.
Möglicherweise haben alle von einer Assembler-Beispielimplementierung abgeschrieben, die auf einem Prozessor implementiert wurde, der BITREV- (Bitreihenfolge in einem Byte umkehren) und ROTATE-Befehle (ähnlich wie SHIFT, aber ausgeschobene Bits links im Carry- und rechts im Zero-Flag halten) hat. Damit läßt sich eine elegante Routine implementieren, die per ROTATE Bits aus einem Byte raus und in das andere einschiebt (dazu muß auf einer Seite die Bitreihenfolge umgedreht werden, dann kommt man mit zwei 8-Bit Registern und dem Flag-/Statusregister aus).
In C bringt das keinen Vorteil (man kann weder Rotieren noch hat man Zugriff auf die Prozessor-Flags). Wenn Du's trotzdem probieren willst, kannst Du ja mal überlegen, wie Du in C die Bitreihenfolge in einem Byte umdrehen würdest...