Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bitreihenfolge umkehren/Operator für binäres Wortspiegeln?

704 views
Skip to first unread message

Robert Hartmann

unread,
Jun 22, 2009, 10:52:38 AM6/22/09
to
Hallo zusammen,

wahrscheinlich hab ich nur einen Bitoperator ᅵbersehen,
zumindest kann ich den nicht finden.

int main(){
unsigned char 8bit = 0xf1;


...

}

Die Variable 8bit hat binᅵr den Wert: 1111 0001

nun suche ich einen Operator, der mir das binᅵre Wort spiegelt,
also als Ergebnis

1000 1111

hat.

Irgendwie hab ich gerade keine Idee mehr,
wie ich die Wortspiegelung selber implementieren kann,
auᅵer jede einzelne Bitstelle abzutesten.

unsigned char spiegelwort(unsignet char wort)
{
unsigned char ret = 0;
for (int pos = 0; pos < 8; pos++)
{
bool value = gibBitAusByte(wort, 8 - pos); /*nur 1 oder 0*/
ret = setzeBitInByte(ret, pos, value);
}
return ret;
}

Schᅵner wᅵre wirklich wenn es fᅵr die Wortspiegelung
etwas gᅵbe ohne zusᅵtzliche Funktionsaufrufe.

Vielleicht sollte ich fᅵr heute damit Schluss machen,
und morgen weiter ᅵberlegen.

Gruᅵ Robert

Falk Tannhäuser

unread,
Jun 22, 2009, 11:36:35 AM6/22/09
to
Robert Hartmann wrote:
> Irgendwie hab ich gerade keine Idee mehr,
> wie ich die Wortspiegelung selber implementieren kann,
> auᅵer jede einzelne Bitstelle abzutesten.

Siehe <http://graphics.stanford.edu/~seander/bithacks.html> und auf
dieser Seite insbesondere den Abschnitt "Reversing bit sequences"
<http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious>
bis <http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel>.

Soll wirklich nur ein 8-Bit-Byte gespiegelt werden, kann man den
letzteren Code-Schnipsel so vereinfachen:


unsigned char v; // 8-bit word to reverse bit order

// swap odd and even bits
v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
// swap consecutive pairs
v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
// swap nibbles ...
v = ((v >> 4) & 0x0F) | ((v & 0x0F) << 4);


MfG
Falk

Heiko Bauke

unread,
Jun 22, 2009, 11:38:02 AM6/22/09
to
Hi,

On Mon, 22 Jun 2009 16:52:38 +0200
Robert Hartmann <Robert_...@gmx.net> wrote:

> wahrscheinlich hab ich nur einen Bitoperator übersehen,


> zumindest kann ich den nicht finden.

dafür gibt es keinen eigenen Operator in C. Man muss sich also eine
Funktion ähnlich der von Dir skizzierten schreiben. Ich würde dieses
Problem wahrscheinlich durch eine Tabelle lösen. Siehe auch
http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious


Heiko


--
-- Es genügt nicht, daß man zur Sache spricht. Man muß
-- zu den Menschen sprechen. (Stanislaw Jerzy Lec)
-- Cluster Computing @ http://www.clustercomputing.de
-- Heiko Bauke @ http://www.mpi-hd.mpg.de/personalhomes/bauke

Jan Seiffert

unread,
Jun 22, 2009, 11:44:20 AM6/22/09
to
Robert Hartmann wrote:
> Hallo zusammen,
>
> wahrscheinlich hab ich nur einen Bitoperator übersehen,

> zumindest kann ich den nicht finden.
>

Nein, dafuer gibt es fix und fertig keinen.

[snip]
> Die Variable 8bit hat binär den Wert: 1111 0001
>
> nun suche ich einen Operator, der mir das binäre Wort spiegelt,


> also als Ergebnis
>
> 1000 1111
>
> hat.
>

Du willst also nicht die Nibble tauschen, sondern wirklich das ding umdrehen?

> Irgendwie hab ich gerade keine Idee mehr,
> wie ich die Wortspiegelung selber implementieren kann,

> außer jede einzelne Bitstelle abzutesten.
>

Jo, the obvious way.

> Schöner wäre wirklich wenn es für die Wortspiegelung
> etwas gäbe ohne zusätzliche Funktionsaufrufe.
>

Nein, so ganz wirst du da nicht drum rum kommen.
Aber du kannst es ja als static inline in einen haeder packen, wenngleich das
einige als unsauber empfinden (Code gehoert nicht in Header), es hat aber in dem
Fall den Vorteil das der Compiler sehen kann, was passiert und die Operation
fuer Konstanten schon bei der Kompiliereung machen kann.

Du hast noch die moeglichkeit mit einer lookup Tabelle.

Falls du C99 hast und dein Compiler gut darin ist Divisionen umzuschreiben und
du einen schnellen Hardware multiplier mit 64 Bit hast (also x86 mit einem neuen
GCC):

unsigned char b; // reverse this (8-bit) byte
b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;

Wobei man da wohl auch einfach das hier nehmen koennte:
b = ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;

Ohne 64 Bit gehts so:
b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;


[snip]
>
> Gruß Robert
>
Gruss
Jan

--
Wir sind die Borg.
Widerstand ist Spannung durch Stromstaerke.

Claus Reibenstein

unread,
Jun 22, 2009, 11:53:56 AM6/22/09
to
Robert Hartmann schrieb:

> wahrscheinlich hab ich nur einen Bitoperator ᅵbersehen,

Nein, hast Du nicht.

> nun suche ich einen Operator, der mir das binᅵre Wort spiegelt,

Gibt es nicht.

> for (int pos = 0; pos < 8; pos++)
> {
> bool value = gibBitAusByte(wort, 8 - pos); /*nur 1 oder 0*/
> ret = setzeBitInByte(ret, pos, value);
> }

for (int pos = 0; pos < 8; ++pos)
ret = (ret << 1) | ((wort >> pos) & 1);

Gruᅵ. Claus

Stefan Reuther

unread,
Jun 22, 2009, 12:10:16 PM6/22/09
to
Robert Hartmann wrote:
> wahrscheinlich hab ich nur einen Bitoperator ᅵbersehen,
> zumindest kann ich den nicht finden.
[...]

> nun suche ich einen Operator, der mir das binᅵre Wort spiegelt,
> also als Ergebnis
>
> 1000 1111

Da gibt's nichts fertiges, das darfst du dir aus den existierenden
Operatoren &|<<>> selber bauen. Eine Sammlung Bit-Fummeleien gibt es
unter <http://graphics.stanford.edu/~seander/bithacks.html>, wobei ich
fᅵr das Umdrehen der Bits
<http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel>
bevorzuge.


Stefan

Michael Schumacher

unread,
Jun 22, 2009, 12:40:30 PM6/22/09
to
Robert Hartmann wrote:

> Die Variable 8bit hat binär den Wert: 1111 0001
> nun suche ich einen Operator, der mir das binäre Wort spiegelt,


> also als Ergebnis 1000 1111 hat.

Operator? Nicht wirklich. Aber Du kannst die inet-Funktionen aus
der htonl()/ntohl()-Familie (<arpa/inet.h>) dafür mißbrauchen.

> Irgendwie hab ich gerade keine Idee mehr,
> wie ich die Wortspiegelung selber implementieren kann,

> außer jede einzelne Bitstelle abzutesten.

Ich mußte sowas mal für eine i86(little endian)/68k(big endian)-
Konvertierung machen; WIMRE benutzte ich dafür eine Lookup-Table,
also ein 256-Byte-Array, in dem 0x00 bis 0xff in umgekehrter
Reihenfolge gespeichert waren. Wenn genug Speicher da ist und
die Performance höchste Priorität hat, kann man natürlich auch
ein 64k-Array (0x0000-0xffff) benutzen. In beiden Fällen dient
der isolierte 8- bzw. 16-bit-Wert als Index. Schneller geht's
eigentlich nur noch, wenn die CPU entsprechende Konvertierungen
zur Verfügung stellt (MIPS kann das, WIMRE), aber dann ist die
Lösung nicht mehr portabel (#ifdef/autoconf/etc. ausgenommen).


mike

Sebastian Biallas

unread,
Jun 22, 2009, 12:54:03 PM6/22/09
to
Michael Schumacher wrote:
> Robert Hartmann wrote:
>
>> Die Variable 8bit hat binär den Wert: 1111 0001
>> nun suche ich einen Operator, der mir das binäre Wort spiegelt,
>> also als Ergebnis 1000 1111 hat.
>
> Operator? Nicht wirklich. Aber Du kannst die inet-Funktionen aus
> der htonl()/ntohl()-Familie (<arpa/inet.h>) dafür mißbrauchen.

Das bezweifel ich.

>> Irgendwie hab ich gerade keine Idee mehr,
>> wie ich die Wortspiegelung selber implementieren kann,
>> außer jede einzelne Bitstelle abzutesten.
>
> Ich mußte sowas mal für eine i86(little endian)/68k(big endian)-
> Konvertierung machen; WIMRE benutzte ich dafür eine Lookup-Table,
> also ein 256-Byte-Array, in dem 0x00 bis 0xff in umgekehrter
> Reihenfolge gespeichert waren.

Big- bzw. little-endian bezieht sich auf die Reihenfolge der Bytes eines
Words im Speicher.

--
Gruß,
Sebastian

Michael Schumacher

unread,
Jun 22, 2009, 2:48:56 PM6/22/09
to
Sebastian Biallas wrote:

> Michael Schumacher wrote:
>> Robert Hartmann wrote:
>>
>>> Die Variable 8bit hat binär den Wert: 1111 0001
>>> nun suche ich einen Operator, der mir das binäre Wort spiegelt,
>>> also als Ergebnis 1000 1111 hat.
>>
>> Operator? Nicht wirklich. Aber Du kannst die inet-Funktionen aus
>> der htonl()/ntohl()-Familie (<arpa/inet.h>) dafür mißbrauchen.
>
> Das bezweifel ich.

Gerne. Und warum? ;-)



>>> Irgendwie hab ich gerade keine Idee mehr,
>>> wie ich die Wortspiegelung selber implementieren kann,
>>> außer jede einzelne Bitstelle abzutesten.
>>
>> Ich mußte sowas mal für eine i86(little endian)/68k(big endian)-
>> Konvertierung machen; WIMRE benutzte ich dafür eine Lookup-Table,
>> also ein 256-Byte-Array, in dem 0x00 bis 0xff in umgekehrter
>> Reihenfolge gespeichert waren.
>
> Big- bzw. little-endian bezieht sich auf die Reihenfolge der Bytes eines
> Words im Speicher.

Naja, es wär' ja einfach, wenn's so einfach wär. Dummerweise gibt's
(oder gab's zumindest) komische Mischformen; die VAX war so ein Unikum.
Es ist eben nicht nur entscheidend, welches Byte "vorne" oder "hinten"
ist, sondern auch, wie die CPU die einzelnen Bits adressiert. Es gibt
einen guten Grund dafür, daß der C-Standard zwar Bitfelder definiert,
aber keinerlei Aussage über ihre tatsächliche Ablage im Speicher macht.


mike

Jan Seiffert

unread,
Jun 22, 2009, 3:02:18 PM6/22/09
to
Michael Schumacher wrote:
> Sebastian Biallas wrote:
>
>> Michael Schumacher wrote:
>>> Robert Hartmann wrote:
>>>
>>>> Die Variable 8bit hat binär den Wert: 1111 0001
>>>> nun suche ich einen Operator, der mir das binäre Wort spiegelt,
>>>> also als Ergebnis 1000 1111 hat.
>>> Operator? Nicht wirklich. Aber Du kannst die inet-Funktionen aus
>>> der htonl()/ntohl()-Familie (<arpa/inet.h>) dafür mißbrauchen.
>> Das bezweifel ich.
>
> Gerne. Und warum? ;-)
>

Weil diese Funktionen eigentlich nur die Bytes umdrehen.

>>>> Irgendwie hab ich gerade keine Idee mehr,
>>>> wie ich die Wortspiegelung selber implementieren kann,
>>>> außer jede einzelne Bitstelle abzutesten.
>>> Ich mußte sowas mal für eine i86(little endian)/68k(big endian)-
>>> Konvertierung machen; WIMRE benutzte ich dafür eine Lookup-Table,
>>> also ein 256-Byte-Array, in dem 0x00 bis 0xff in umgekehrter
>>> Reihenfolge gespeichert waren.
>> Big- bzw. little-endian bezieht sich auf die Reihenfolge der Bytes eines
>> Words im Speicher.
>
> Naja, es wär' ja einfach, wenn's so einfach wär. Dummerweise gibt's
> (oder gab's zumindest) komische Mischformen; die VAX war so ein Unikum.

Noe, die VAX war AFAIK recht normal und fortschrittlich, darum ja die Flueche
ueber die "All the world is a VAX"-Programmierer von den legacy Freunden.

> Es ist eben nicht nur entscheidend, welches Byte "vorne" oder "hinten"
> ist, sondern auch, wie die CPU die einzelnen Bits adressiert.

Naja, eine CPU addressiert selten Bits.
Und zweimal "gedreht" (beim kopieren in den Speicher, beim wieder rausholen aus
dem Speicher) ist weider richtig rum.

Dumm ist es nur, wenn einer Peripherie, z.B. die Netzwerkarte mit den
Datenleitungen verdreht angeschlossen hat. Von der liest man nur einmal.

Das passiert schon mal wenn auf der CPU der Hersteller von LSB zu MSB zaehlt
(LSB ist 0, MSB ist z.B. 31), der Netzwerkchip Hersteller von MSB zu LSB (MSB
ist 0, LSB ist 31). Wenn man nun 1:1 routet, D0 auf D0 ... D31 auf D31, ist der
Bock fett.
Dann ist es aber Aufgabe des Treibers auf der Maschine mit der vergurkten
Boardlayout das wieder grade zu ziehen.
Nicht ich als Sender im die Bits mundgerecht zu Kloeppeln.

[snip]
>
> mike
>
Gruss
Jan

--
Networking? That is for fishermen.

Sebastian Biallas

unread,
Jun 22, 2009, 3:27:26 PM6/22/09
to
Michael Schumacher wrote:
> Sebastian Biallas wrote:
>
>> Michael Schumacher wrote:
>>> Robert Hartmann wrote:
>>>
>>>> Die Variable 8bit hat binär den Wert: 1111 0001
>>>> nun suche ich einen Operator, der mir das binäre Wort spiegelt,
>>>> also als Ergebnis 1000 1111 hat.
>>> Operator? Nicht wirklich. Aber Du kannst die inet-Funktionen aus
>>> der htonl()/ntohl()-Familie (<arpa/inet.h>) dafür mißbrauchen.
>> Das bezweifel ich.
>
> Gerne. Und warum? ;-)

Na macht doch mal vor :)

>>>> Irgendwie hab ich gerade keine Idee mehr,
>>>> wie ich die Wortspiegelung selber implementieren kann,
>>>> außer jede einzelne Bitstelle abzutesten.
>>> Ich mußte sowas mal für eine i86(little endian)/68k(big endian)-
>>> Konvertierung machen; WIMRE benutzte ich dafür eine Lookup-Table,
>>> also ein 256-Byte-Array, in dem 0x00 bis 0xff in umgekehrter
>>> Reihenfolge gespeichert waren.
>> Big- bzw. little-endian bezieht sich auf die Reihenfolge der Bytes eines
>> Words im Speicher.
>
> Naja, es wär' ja einfach, wenn's so einfach wär.

Es ist so einfach, jedenfalls wenn ein Byte ein Oktett ist.

> Dummerweise gibt's
> (oder gab's zumindest) komische Mischformen; die VAX war so ein Unikum.

Du kannst statt big oder little-endian natürlich noch sämtliche andere
Byte-Permutation durchgehen. Mit Bitfummelei hat es immer noch nicht
viel zu tun.

> Es ist eben nicht nur entscheidend, welches Byte "vorne" oder "hinten"
> ist, sondern auch, wie die CPU die einzelnen Bits adressiert.

Die Bit-Endianess ist aber nur eine Konvention, wo man anfängt zu zählen
(wenn man überhaupt Befehle hat, die Bits adressieren können).
Byte-Endianess und Bit-Endianess sind aber auch beliebig mischbar.

Ich hab jedenfalls schon diverse CPU-Simulatoren geschrieben, und musste
noch nie ein Bitreverse dafür schreiben.

> Es gibt
> einen guten Grund dafür, daß der C-Standard zwar Bitfelder definiert,
> aber keinerlei Aussage über ihre tatsächliche Ablage im Speicher macht.

Ob dieser Grund "gut" ist, sei jetzt mal dahingestellt. Es hat
jedenfalls einen guten Grund, dass der Ausdruck (x & 1) in C immer das
LSB testet.

--
Gruß,
Sebastian

Rainer Weikusat

unread,
Jun 23, 2009, 6:01:51 AM6/23/09
to
Sebastian Biallas <groups...@spamgourmet.com> writes:
> Michael Schumacher wrote:

[...]

>> Es ist eben nicht nur entscheidend, welches Byte "vorne" oder "hinten"
>> ist, sondern auch, wie die CPU die einzelnen Bits adressiert.
>

> Die Bit-Endianess ist aber nur eine Konvention, wo man anf�ngt zu
> z�hlen (wenn man �berhaupt Befehle hat, die Bits adressieren
> k�nnen).

Sie ist vor allem auch eine Konvention, in welcher Reihenfolge Bits
ueber irgendein 'geeignetes Medium' uebertragen werden.

Juergen Ilse

unread,
Jun 23, 2009, 8:35:31 AM6/23/09
to
Hallo,

Michael Schumacher <mi...@gmx.de> wrote:


> Sebastian Biallas wrote:
>> Big- bzw. little-endian bezieht sich auf die Reihenfolge der Bytes eines
>> Words im Speicher.
> Naja, es wär' ja einfach, wenn's so einfach wär.

Es *ist* so einfach.

> Dummerweise gibt's (oder gab's zumindest) komische Mischformen; die VAX
> war so ein Unikum.

... oder die PDP11, ja. Aber die "Abnormitaet" lag dort nmoch immer in der
Reihenfolge der Bytes, nicht in der Adressierbarkeit der Bits. Bei "long"
(sprich: 4-byte-Werten) war die Reihenfolge der Bytes im Speicher weder
1234 (littleendian) noch 4321 (bigendian) sondern 2143 (d.h. die unteren
16 Bit lagen im Speicher vorn, allerdings in bigendian-Reihenfolge, die
oberen 16 Bit ebenfalls in bigendian-Reihenfolge dahinter, das war eben
éine 16-Bit-Maschine, was diese Reihenfolge dann wieder irgendwie logisch
macht ...).

> Es ist eben nicht nur entscheidend, welches Byte "vorne" oder "hinten"
> ist, sondern auch, wie die CPU die einzelnen Bits adressiert.

Die CPU adressiert i.d.R. gar keine Bits (von einigen exotischen CPUs
fuer Speziealaufgaben abgesehen). Die kleinste fuer die CPU adressier-
bare einheit ist i.d.R. ein Byte (bei einigen CPUs sogar ein 32-Bit-Wort,
einige der DEC-Alpha-CPUs fallen mir da als Beispiel ein ...).

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)
--
Ein Domainname (auch wenn er Teil einer Mailadresse ist) ist nur ein Name,
nicht mehr und nicht weniger ...

Rainer Weikusat

unread,
Jun 23, 2009, 8:52:26 AM6/23/09
to
Juergen Ilse <jue...@usenet-verwaltung.de> writes:
> Michael Schumacher <mi...@gmx.de> wrote:
>> Sebastian Biallas wrote:
>>> Big- bzw. little-endian bezieht sich auf die Reihenfolge der Bytes eines
>>> Words im Speicher.
>> Naja, es w�r' ja einfach, wenn's so einfach w�r.
>
> Es *ist* so einfach.

Nicht wirklich. Zusaetzlich zu dem bereits genannten
Serialisierungsproblem kommt ausserdem noch, dass 'manche Leute' sich
ausgesprochen wirre Verdrahtungen (besserer Begriff?) wenigstens von
FLASH-ROMs einfallen lassen, wenn dadurch die Hardware irgendeine
'wuenschenswerte' Eigenschaft erhaelt, vgl

config MTD_CFI_NOSWAP
bool "NO"
---help---
This option defines the way in which the CPU attempts to arrange
data bits when writing the 'magic' commands to the
chips.

[...]

If you have a LART, on which the data (and address) lines were
connected in a fashion which ensured that the nets were as short
as possible, resulting in a bit-shuffling which seems utterly
random to the untrained eye, you need the LART_ENDIAN_BYTE option.

Yes, there really exists something sicker than PDP-endian :)
[drivers/mtd/chips/Kconfig, Linux 2.6.30]

Jan Seiffert

unread,
Jun 23, 2009, 10:50:14 AM6/23/09
to
Rainer Weikusat wrote:
> Juergen Ilse <jue...@usenet-verwaltung.de> writes:
>> Michael Schumacher <mi...@gmx.de> wrote:
>>> Sebastian Biallas wrote:
>>>> Big- bzw. little-endian bezieht sich auf die Reihenfolge der Bytes eines
>>>> Words im Speicher.
>>> Naja, es wär' ja einfach, wenn's so einfach wär.

>> Es *ist* so einfach.
>
> Nicht wirklich. Zusaetzlich zu dem bereits genannten
> Serialisierungsproblem kommt ausserdem noch, dass 'manche Leute' sich
> ausgesprochen wirre Verdrahtungen (besserer Begriff?) wenigstens von
> FLASH-ROMs einfallen lassen, wenn dadurch die Hardware irgendeine
> 'wuenschenswerte' Eigenschaft erhaelt, vgl
>
> config MTD_CFI_NOSWAP
> bool "NO"
> ---help---
> This option defines the way in which the CPU attempts to arrange
> data bits when writing the 'magic' commands to the
> chips.
>
> [...]
>
> If you have a LART, on which the data (and address) lines were
> connected in a fashion which ensured that the nets were as short
> as possible, resulting in a bit-shuffling which seems utterly
> random to the untrained eye, you need the LART_ENDIAN_BYTE option.
>

Nein, bitte nicht...
Aua.
Weil sie die Leiterbahnen kurz halten wollten haben sie das ding IRGENDWIE
angeschlossen und der Softwerker darf jetzt bei jedem Zugriff die Bits passend
friemeln?
Aua.
Nur weil die Pins manchmal unguenstig um einen IC verteilt sind heisst das noch
lange nicht, das der Hardwerker dann das Problem an den Softwerker auslagern
kann, es gibt so Dinge, die muessen einfach in Hardware gemacht werden...

> Yes, there really exists something sicker than PDP-endian :)
> [drivers/mtd/chips/Kconfig, Linux 2.6.30]

Gruss
Jan

--
"Immer ein Bit überbehalten!"

Stefan Reuther

unread,
Jun 23, 2009, 12:21:54 PM6/23/09
to
Jan Seiffert wrote:

> Rainer Weikusat wrote:
>> config MTD_CFI_NOSWAP
>> bool "NO"
>> ---help---
>> This option defines the way in which the CPU attempts to arrange
>> data bits when writing the 'magic' commands to the
>> chips.
>
> Nein, bitte nicht...
> Aua.
> Weil sie die Leiterbahnen kurz halten wollten haben sie das ding IRGENDWIE
> angeschlossen und der Softwerker darf jetzt bei jedem Zugriff die Bits passend
> friemeln?
> Aua.

Warum nicht? Bei einem klassischen SRAM ist z.B. völlig egal, wie die
Daten- und Adressbits verdrahtet sind. Auch beim SDRAM kann man in
gewissen Grenzen permutieren.

Und wenn man bei einem Flash die Datenbits komisch verdrahtet, müssen
halt die Befehle einer konstanten Permutation unterzogen werden. Das
macht man zur Compilezeit, oder zur Not mit einer Lookup-Table. Das kann
jedenfalls *deutlich* einfacher sein als die Leiterzüge zu entwirren.


Stefan

Robert Hartmann

unread,
Jun 24, 2009, 10:15:54 AM6/24/09
to
Hallo zusammen,

danke fᅵr die mehrfachen Hinweise auf
http://graphics.stanford.edu/~seander/bithacks.html
die ist wirklich interessant.

Ich hab nun auf zwei verschiedene Weisen
das Wortspiegeln implementiert (siehe unten):

spiegelBitsInByteVersion1, spiegelBitsInByteVersion2 .

Ich nehme an, dass Version 2 schneller abgearbeitet wird.


Dann hab ich ein kleines Testprogramm geschrieben,
seltsamerweise bekomme ich

bei der Funktion BitsInByteToCharArray

das gespiegelte Byte ordentlich zurᅵckgegeben und kann es mit
printf ausgeben, jedoch das original Byte nicht.

char A[CHAR_BIT]; BitsInByteToCharArray(Byte ,A);
char S[CHAR_BIT]; BitsInByteToCharArray(SpiegelByte2 ,S);

printf("Als CArray: Original %s", &A); /*kein Wert sichtbar*/
printf("und gespiegelt %s", &S); /*Wert sichtbar*/

Hab ich etwas bei der Funktion BitsInByteToCharArray ᅵbersehen?

Die Funktion printBitsInByte funktioniert fᅵr beide Fᅵlle.

Gruᅵ Robert

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

unsigned char spiegelBitsInByteVersion1(unsigned char theByte){
unsigned char ret1 = 0;
for (unsigned char bitPos=0; bitPos < CHAR_BIT; bitPos++)
{
if( (((1 << bitPos)&theByte) >> bitPos) == 1 )
ret1 = (ret1 | (1 << (CHAR_BIT-1)-bitPos));
}
return ret1;
}

unsigned char spiegelBitsInByteVersion2(unsigned char theByte){
unsigned char ret2 = 0;
for (unsigned char bitPos=0; bitPos < CHAR_BIT; bitPos++)
{
ret2 = (((theByte >> bitPos)&1)|(ret2 << 1)) ;
}
return ret2;
}

void printBitsInByte(const unsigned char theByte){
for (size_t bitPos=0; bitPos < CHAR_BIT; bitPos++)
{
printf("%d",((theByte >> CHAR_BIT-1-bitPos)&1));
/* if(bitPos==3) printf("."); */
}
printf("\n");
}

char* BitsInByteToCharArray(const unsigned char theByte, char* ByteAsText){
if (ByteAsText == NULL) return NULL;
unsigned char bitPos = 0;
for (bitPos=0; bitPos < CHAR_BIT; bitPos++)
{
if(((theByte >> CHAR_BIT-1-bitPos)&1)==1)
ByteAsText[bitPos]= '1';
else ByteAsText[bitPos]= '0';
}
ByteAsText[CHAR_BIT] = '\0';
return ByteAsText;
}

int main(int argc, char* argv[]){
unsigned char Byte = 0xF1;

unsigned char SpiegelByte1 = spiegelBitsInByteVersion1(Byte);
unsigned char SpiegelByte2 = spiegelBitsInByteVersion2(Byte);

printf("Das original Byte: "); printBitsInByte(Byte);

printf("Das gespiegelte Byte (Version 1): ");
printBitsInByte(SpiegelByte1);

printf("Das gespiegelte Byte (Version 2): ");
printBitsInByte(SpiegelByte2);


char A[CHAR_BIT]; BitsInByteToCharArray(Byte ,A);
char S[CHAR_BIT]; BitsInByteToCharArray(SpiegelByte2 ,S);

printf("Als CArray: Original %s", &A);
printf("und gespiegelt %s", &S);

return 0;
}

Achim Peters

unread,
Jun 24, 2009, 12:10:46 PM6/24/09
to
Robert Hartmann schrieb:

> Ich hab nun auf zwei verschiedene Weisen
> das Wortspiegeln implementiert (siehe unten):

> Dann hab ich ein kleines Testprogramm geschrieben,


> seltsamerweise bekomme ich
>
> bei der Funktion BitsInByteToCharArray
>
> das gespiegelte Byte ordentlich zurᅵckgegeben und kann es mit
> printf ausgeben, jedoch das original Byte nicht.

> printf("Als CArray: Original %s", &A); /*kein Wert sichtbar*/


> printf("und gespiegelt %s", &S); /*Wert sichtbar*/

Ich wᅵrde bitverfummelte Chars nicht per printf(%s) ausgeben. Es scheint
doch eher unwahrscheinlich, dass vorher und nachher druckbare Zeichen
entstehen.

Bye
Achim

Dirk Ruth

unread,
Jun 24, 2009, 2:06:05 PM6/24/09
to
Claus Reibensteinschrieb:
"
>Robert Hartmann schrieb:
>
>> wahrscheinlich hab ich nur einen Bitoperator �bersehen,
>
>Nein, hast Du nicht.
>
>> nun suche ich einen Operator, der mir das bin�re Wort spiegelt,

>
>Gibt es nicht.
>
>> for (int pos = 0; pos < 8; pos++)
>> {
>> bool value = gibBitAusByte(wort, 8 - pos); /*nur 1 oder 0*/
>> ret = setzeBitInByte(ret, pos, value);
>> }
>
> for (int pos = 0; pos < 8; ++pos)
> ret = (ret << 1) | ((wort >> pos) & 1);
>
>Gru�. Claus

Das sieht aber alles recht aufwendig aus.
Normalerweise kennt doch fast jeder Prozessor/Controller auch
Verschiebe- und Rotationsbefehle durch das Carry-Flag.

Also einmal links schieben der Eingangsdaten ins Carry, dann
rechtsschieben der Ausgangsdaten aus dem Carry. Das Ganze achtmal
wiederholen.

W�re nat�rlich kein reines C mehr.

Dirk

Claudio Carobolante

unread,
Jun 24, 2009, 2:11:10 PM6/24/09
to
Dirk Ruth schrieb:

> Das sieht aber alles recht aufwendig aus.

> Normalerweise [...]
>
> Wᅵre natᅵrlich kein reines C mehr.

Also eine Lᅵsung, die hier nichts zu suchen hat.

cc

Dirk Ruth

unread,
Jun 24, 2009, 2:31:34 PM6/24/09
to
Claudio Carobolanteschrieb:

"
>Dirk Ruth schrieb:
>
>> Das sieht aber alles recht aufwendig aus.
>> Normalerweise [...]
>>
>> W�re nat�rlich kein reines C mehr.
>
>Also eine L�sung, die hier nichts zu suchen hat.
>

Warum denn so aggressiv? Schlecht getr�umt?

Dirk

Claudio Carobolante

unread,
Jun 24, 2009, 3:44:18 PM6/24/09
to
Dirk Ruth schrieb:

> Claudio Carobolanteschrieb:
>>Dirk Ruth schrieb:
>>
>>> Das sieht aber alles recht aufwendig aus.
>>> Normalerweise [...]
>>>
>>> Wᅵre natᅵrlich kein reines C mehr.
>>
>>Also eine Lᅵsung, die hier nichts zu suchen hat.
>>
> Warum denn so aggressiv? Schlecht getrᅵumt?

Nein. Nur eine fehlerhafte Wahrnehmung deinerseits. Meine Feststellung
ist vollkommen emotionslos. Wenn ich mich aufrege klingt das anders.

cc

Robert Hartmann

unread,
Jun 25, 2009, 4:02:52 AM6/25/09
to
Achim Peters schrieb:

Eben drum mach ich das ja auch gar nicht.


Die Variable A, definiert in der main-Funktion mit der Anweisung
char A[CHAR_BIT]; , ist ein Array von char mit Platz fᅵr genau CHAR_BIT
Zeichen -- mein Compiler lᅵst CHAR_BIT als 8 auf.

Dann kommt der Aufruf:

BitsInByteToCharArray(Byte, A);

Hier sollte jedes Bit in der Variable Byte ᅵberprᅵft und
in A an der entsprechenden ArrayPosition in ein char '1' oder '0'
entsprechend dem ᅵberprᅵfungsergebnis geschrieben werden.

Nun werfen wir zusammen nochmal einen Blick auf die
Implementation von BitsInByteToCharArray.

char* BitsInByteToCharArray(const unsigned char theByte,

char ByteAsText[]){

if (ByteAsText == NULL) return NULL;
unsigned char bitPos = 0;
for (bitPos=0; bitPos < CHAR_BIT; bitPos++){

if(((theByte >> ((CHAR_BIT-1)-bitPos))&1)==1)


ByteAsText[bitPos]= '1';
else ByteAsText[bitPos]= '0';
}
ByteAsText[CHAR_BIT] = '\0';

printf("Innerhalb von BitsInByteToCharArray: %s \n",
ByteAsText);

return ByteAsText;
}

Ehrlich gesagt sehe ich nicht, wo hier das Problem sein kᅵnnte.

Um zuschauen, ob es an der Funktion selber liegt, habe ich eine
Debugausgabe in die Funktion eingefᅵgt. Die Debugausgabe zeigt
die erwartete 0-1-Kombination auch an (original und gespiegelt),
jedoch in der main scheint dies zumindest fᅵr das original Wort
nicht mehr zu funktionieren.

Gruᅵ Robert


KOMPLETTER CODE, um ein paar Klammerungen erweitert,
zudem noch erweitert um ein paar Debug-Ausgaben.

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

unsigned char spiegelBitsInByteVersion1(unsigned char theByte){
unsigned char ret1 = 0;
for (unsigned char bitPos=0; bitPos < CHAR_BIT; bitPos++)
{
if( (((1 << bitPos)&theByte) >> bitPos) == 1 )

ret1 = (ret1 | (1 << ((CHAR_BIT-1)-bitPos)));
}
return ret1;
}

unsigned char spiegelBitsInByteVersion2(unsigned char theByte){
unsigned char ret2 = 0;
for (unsigned char bitPos=0; bitPos < CHAR_BIT; bitPos++)
{
ret2 = (((theByte >> bitPos)&1)|(ret2 << 1)) ;
}
return ret2;
}

void printBitsInByte(const unsigned char theByte){
for (size_t bitPos=0; bitPos < CHAR_BIT; bitPos++){

printf("%d",((theByte >> ((CHAR_BIT-1)-bitPos))&1));
//if(bitPos==3) printf(".");
}
printf("\n");
}

char* BitsInByteToCharArray(const unsigned char theByte, char ByteAsText[]){


if (ByteAsText == NULL) return NULL;
unsigned char bitPos = 0;
for (bitPos=0; bitPos < CHAR_BIT; bitPos++){

if(((theByte >> ((CHAR_BIT-1)-bitPos))&1)==1)


ByteAsText[bitPos]= '1';
else ByteAsText[bitPos]= '0';
}
ByteAsText[CHAR_BIT] = '\0';

printf("Innerhalb von BitsInByteToCharArray: %s \n", ByteAsText);

return ByteAsText;
}

int main(int argc, char* argv[]){
unsigned char Byte = 0xF1;

unsigned char SpiegelByte1 = spiegelBitsInByteVersion1(Byte);
unsigned char SpiegelByte2 = spiegelBitsInByteVersion2(Byte);

printf("\n");
printf("Test der Funktion printBitsInByte(const unsigned char theByte):
\n \n");


printf("Das original Byte: "); printBitsInByte(Byte);
printf("Das gespiegelte Byte (Version 1): ");
printBitsInByte(SpiegelByte1);
printf("Das gespiegelte Byte (Version 2): ");
printBitsInByte(SpiegelByte2);

printf("\n");
printf("\n");

printf("Test der Funktion \nchar* BitsInByteToCharArray(const unsigned
char theByte, char ByteAsText[]) \n \n");
char A[CHAR_BIT];
printf("Aufruf von BitsInByteToCharArray mit original Byte: \n");
BitsInByteToCharArray(Byte ,A);
printf("\n");
char S[CHAR_BIT];
printf("Aufruf von BitsInByteToCharArray mit gespiegeltem Byte: \n");
BitsInByteToCharArray(SpiegelByte2 ,S);
printf("\n");
printf("Ergebnis von BitsInByteToCharArray in main-Funktion: Original
%s \n", A);
printf("Ergebnis von BitsInByteToCharArray in main-Funktion: Gespiegelt
%s", S);
printf("\n");
return 0;
}


Gruᅵ Robert

Robert Hartmann

unread,
Jun 25, 2009, 5:25:03 AM6/25/09
to
Hallo zusammen,

Das Problem mit der vergessenen Angabe lag
an keiner anderen als der main-Funktion.

> Die Variable A, definiert in der main-Funktion mit der Anweisung
> char A[CHAR_BIT]; , ist ein Array von char mit Platz fᅵr genau CHAR_BIT
> Zeichen -- mein Compiler lᅵst CHAR_BIT als 8 auf.

und genau das war auch das Problem :-)
Ich hᅵtte char A[CHAR_BIT+1];
und char S[CHAR_BIT+1];
schreiben mᅵssen, um ein Array mit Platz fᅵr
CHAR_BIT Zeichen zu schaffen.

Gruᅵ Robert

Achim Peters

unread,
Jun 25, 2009, 5:24:20 AM6/25/09
to
Robert Hartmann wrote:
> Achim Peters schrieb:
>> Robert Hartmann schrieb:
>>> Dann hab ich ein kleines Testprogramm geschrieben,
>>> seltsamerweise bekomme ich
>>>
>>> bei der Funktion BitsInByteToCharArray
>>>
>>> das gespiegelte Byte ordentlich zurᅵckgegeben und kann es mit
>>> printf ausgeben, jedoch das original Byte nicht.
>>
>>> printf("Als CArray: Original %s", &A); /*kein Wert sichtbar*/
>>> printf("und gespiegelt %s", &S); /*Wert sichtbar*/
>>
>> Ich wᅵrde bitverfummelte Chars nicht per printf(%s) ausgeben.

> Eben drum mach ich das ja auch gar nicht.

> Die Variable A, definiert in der main-Funktion mit der Anweisung
> char A[CHAR_BIT]; , ist ein Array von char mit Platz fᅵr genau CHAR_BIT
> Zeichen -- mein Compiler lᅵst CHAR_BIT als 8 auf.
>
> Dann kommt der Aufruf:
>
> BitsInByteToCharArray(Byte, A);
>
> Hier sollte jedes Bit in der Variable Byte ᅵberprᅵft und
> in A an der entsprechenden ArrayPosition in ein char '1' oder '0'
> entsprechend dem ᅵberprᅵfungsergebnis geschrieben werden.

Wie wᅵr's stattdessen mit
char c;
printf("%02x", c);

Bye
Achim

Claus Reibenstein

unread,
Jun 25, 2009, 5:34:10 AM6/25/09
to
Dirk Ruth schrieb:

> Claus Reibensteinschrieb:


>
>> for (int pos = 0; pos < 8; ++pos)
>> ret = (ret << 1) | ((wort >> pos) & 1);
>

> Das sieht aber alles recht aufwendig aus.

Was, bitte sch�n, ist denn an diesen beiden Zeilen aufw�ndig?

> Normalerweise kennt doch fast jeder Prozessor/Controller auch
> Verschiebe- und Rotationsbefehle durch das Carry-Flag.

Prozessoren kennen vieles, was C nicht kennt, und C kennt vieles, was
Prozessoren nicht kennen.

Auf Assemblerebene kann man solche Features sicherlich nutzen. In C
jedoch nicht, weil sie dort einfach nicht zur Verf�gung stehen. C kennt
einfach kein "Carry-Flag".

> W�re nat�rlich kein reines C mehr.

Und ist hier in dclc deshalb off topic.

Gru�. Claus

Robert Hartmann

unread,
Jun 25, 2009, 5:38:04 AM6/25/09
to
Hallo zusammen,

Das Problem mit der vergessenen Angabe lag
an keiner anderen als der main-Funktion.

> Die Variable A, definiert in der main-Funktion mit der Anweisung


> char A[CHAR_BIT]; , ist ein Array von char mit Platz fᅵr genau CHAR_BIT
> Zeichen -- mein Compiler lᅵst CHAR_BIT als 8 auf.

und genau das war auch das Problem :-)


Ich hᅵtte char A[CHAR_BIT+1];
und char S[CHAR_BIT+1];
schreiben mᅵssen, um ein Array mit Platz fᅵr
CHAR_BIT Zeichen zu schaffen.

Nun muss man ein char-Array mit '\0' terminieren,
um es mit printf ᅵber %s korrekt ausgeben zu kᅵnnen,
also braucht man Platz im Array fᅵr CHAR_BIT Zeichen
(nᅵmlich die Kombination von Nullen und/oder Einsen)
plus dem Terminalzeichen '\0', d.h. das Array braucht
Platz fᅵr CHAR_BIT+1 Zeichen:

Damit lautet also die Definition fᅵr so ein Array,
eben weder char Name[CHAR_BIT]; noch char Name[CHAR_BIT+1];
sondern char Name[CHAR_BIT+2];

Gruᅵ Robert


Claus Reibenstein

unread,
Jun 25, 2009, 5:48:16 AM6/25/09
to
Achim Peters schrieb:

> Robert Hartmann wrote:
>
>> Hier sollte jedes Bit in der Variable Byte ᅵberprᅵft und
>> in A an der entsprechenden ArrayPosition in ein char '1' oder '0'
>> entsprechend dem ᅵberprᅵfungsergebnis geschrieben werden.
>
> Wie wᅵr's stattdessen mit
> char c;
> printf("%02x", c);

Das gibt Werte binᅵr als Nullen und Einsen aus? Wᅵre mir neu.

Gruᅵ. Claus

Achim Peters

unread,
Jun 25, 2009, 8:12:57 AM6/25/09
to
Claus Reibenstein schrieb:

Wenn ich einen zweistelligen Hexwert sehe, "sehe" ich binᅵre Nullen und
Einsen. Zum Debuggen sollte es reichen.

Bye
Achim

Robert Hartmann

unread,
Jun 25, 2009, 9:16:11 AM6/25/09
to
Hallo Achim,

Achim Peters schrieb:

Und wozu genau soll das hilfreich sein, wenn man eine Funktion
implementieren will, die als Rᅵckgabe ein c-string (== char[] == *char)
haben soll, der die einzelnen Bitstellen des ᅵbergababeparameters vom
Typ unsigned char reprᅵsentiert?

Gruᅵ Robert

Achim Peters

unread,
Jun 25, 2009, 9:44:56 AM6/25/09
to
Robert Hartmann schrieb:

Ich dachte, Du wolltest gemᅵᅵ Subject Bitreihenfolgen umkehren und das
Ergebnis davon dann ᅵberprᅵfen. Das Ergebnis einer Bitverfummlung kann
man sich auch mit dem printf("%02x", c) anschauen.

Deswegen schlug ich das printf("%02x", c) vor, zumal die von Dir
beschrieben Funktion ja zu diesem Zeitpunkt nicht das gewᅵnschte leistete.

Bye
Achim

Markus Wichmann

unread,
Jun 25, 2009, 9:33:49 AM6/25/09
to
[Subject gekürzt, obwohl nonstandard]

Robert Hartmann <Robert_...@gmx.net> wrote:
> Hallo zusammen,
>
> Ich hätte char A[CHAR_BIT+1];
> und char S[CHAR_BIT+1];
> schreiben müssen, um ein Array mit Platz für
> CHAR_BIT Zeichen zu schaffen.
>

Nein. Aber in C sind alle Arrays auf 0 basiert. Sprich, angenommen
CHAR_BITS==8, dann ergibt »char A[CHAR_BITS];« ein Feld mit 8 Bytes
Größe (Ja, ein Char ist immer ein Byte. Aber ein Byte sind nicht
notwenigerweise 8 Bit) und den Indizes 0 bis 7.

> Nun muss man ein char-Array mit '\0' terminieren,

> um es mit printf über %s korrekt ausgeben zu können,
> also braucht man Platz im Array für CHAR_BIT Zeichen
> (nämlich die Kombination von Nullen und/oder Einsen)


> plus dem Terminalzeichen '\0', d.h. das Array braucht

> Platz für CHAR_BIT+1 Zeichen:
>

Richtig, du willst ja einen echten C-String erzeugen (der sich nicht nur
durch den Typen »char*« auszeichnet, sondern auch durch die
abschließende 0).

> Damit lautet also die Definition für so ein Array,


> eben weder char Name[CHAR_BIT]; noch char Name[CHAR_BIT+1];
> sondern char Name[CHAR_BIT+2];
>

Nein, das wäre Byteverschwendung :-). Sicher, das macht bei heutigen
Rechnern nix aus, aber unschön ist es dennoch. Um CHAR_BITS+1 Zeichen
aufnehmen zu können, muss ein Feld so deklariert werden: »char
A[CHAR_BITS+1];«, hat dann aber die Indizes 0 bis CHAR_BITS. D.h.
»A[CHAR_BITS+1]« ist dann eine ungültige Referenz.

Merke: Computer fangen sehr häufig bei 0 an zu zählen. Dem muss sich ein
Programmierer entweder anpassen, oder mithilfe der richtigen Sprachen
überwinden: Mich stört es nicht, dass ein Feld immer bei 0 beginnt,
Pascal-Programmierer können ein Feld überall beginnen lassen, wo es
gerade passt. Jedem wie es ihm gefällt.

> Gruß Robert
>

Tschö,
Markus

P.S.: Wie in diesem Thread wieder mal klar wurde: Ein Feature, das C
immer nachgesagt wird, existiert nicht portabel, nämlich die
»Hardwarenähe«: Jeder Mikroprozessor und -controller dieser Welt hat
Flags wie Carry und Overflow, aber mit Standard-C kommt man da nicht
dran. Dabei wäre gerade die Overflow-Flag manchmal sehr schön zu
gebrauchen. Aber nein, ein C-Programmierer muss sich um
Overflow-Absicherung selbst kümmern.

--
GUI - ein Hintergrundbild und zwölf XTerms

vim -c "exec \"norm iwHFG#NABGURE#IVZ#UNPXRE\"|%s/#/ /g|norm g??g~~"

Rainer Weikusat

unread,
Jun 25, 2009, 3:01:11 PM6/25/09
to
Markus Wichmann <null...@gmx.net> writes:
> [Subject gek�rzt, obwohl nonstandard]

> Robert Hartmann <Robert_...@gmx.net> wrote:
>> Hallo zusammen,
>>
>> Ich h�tte char A[CHAR_BIT+1];
>> und char S[CHAR_BIT+1];
>> schreiben m�ssen, um ein Array mit Platz f�r

>> CHAR_BIT Zeichen zu schaffen.
>>
>
> Nein. Aber in C sind alle Arrays auf 0 basiert. Sprich, angenommen
> CHAR_BITS==8, dann ergibt �char A[CHAR_BITS];� ein Feld mit 8 Bytes
> Gr��e (Ja, ein Char ist immer ein Byte. Aber ein Byte sind nicht

> notwenigerweise 8 Bit) und den Indizes 0 bis 7.

[...]

> Merke: Computer fangen sehr h�ufig bei 0 an zu z�hlen. Dem muss sich ein


> Programmierer entweder anpassen, oder mithilfe der richtigen Sprachen

> �berwinden: Mich st�rt es nicht, dass ein Feld immer bei 0 beginnt,
> Pascal-Programmierer k�nnen ein Feld �berall beginnen lassen, wo es
> gerade passt.

Ein Feld in C ist etwas vollkommen anderes als ein Feld in Pascal,
naemlich lediglich eine lueckenlose Folge von sequentiell allozierten
Objekten eines bestimmten Typs, die keinerlei Laufzeitidentitaet hat.
Zugriffe auf Feldelemente erfolgen ausschliesslich mit Hilfe von
<Zeiger, Distanz>-Paaren. Logischerweise ist die Entfernung des ersten
Feldelementes vom Feldanfang 0. Damit geht dann zum Beispiel sowas:

p = *path == '/' ? path + 1 : path;
while ((p = strchr(p, '/'))) {
*p++ = 0;

rc = chdir(path);
if (rc == -1)
switch (errno) {
case ENOENT:
rc = eli_wait_for_file(path, file_created, NULL);
if (rc == ELI_WFF_ERROR) exit(1);

rc = chdir(path);
rc != -1 || sys_die(__func__, "chdir");
break;

default:
sys_die(__func__, "chdir");
}

path = p;
}

wofuer man in Pascal einiges an Kniebeugen braeuchte.

Markus Wichmann

unread,
Jun 29, 2009, 10:42:41 AM6/29/09
to
Rainer Weikusat <rwei...@mssgmbh.com> wrote:
> Ein Feld in C ist etwas vollkommen anderes als ein Feld in Pascal,
> naemlich lediglich eine lueckenlose Folge von sequentiell allozierten
> Objekten eines bestimmten Typs, die keinerlei Laufzeitidentitaet hat.

Nanu? Das trifft auf Pascal doch ebenso zu.

> Zugriffe auf Feldelemente erfolgen ausschliesslich mit Hilfe von
><Zeiger, Distanz>-Paaren. Logischerweise ist die Entfernung des ersten
> Feldelementes vom Feldanfang 0.

Das ist der Unterschied. Wobei... in Pascal muss man halt die Nummer des
ersten Elementes kennen, dann ergibt sich der Abstand aus der Differenz
des Feldindex und des Anfangselements.

BTW: Ja, ich weiß das durchaus, aber dem OP schien es nicht klar zu
sein, denn er wollte zur Allokation von CHAR_BITS+1 Zeichen ein Feld der
Größe CHAR_BITS+2 anlegen.

> Damit geht dann zum Beispiel sowas:
>
> p = *path == '/' ? path + 1 : path;
> while ((p = strchr(p, '/'))) {
> *p++ = 0;
>
> rc = chdir(path);
> if (rc == -1)
> switch (errno) {
> case ENOENT:
> rc = eli_wait_for_file(path, file_created, NULL);
> if (rc == ELI_WFF_ERROR) exit(1);
>
> rc = chdir(path);
> rc != -1 || sys_die(__func__, "chdir");
> break;
>
> default:
> sys_die(__func__, "chdir");
> }
>
> path = p;
> }
>
> wofuer man in Pascal einiges an Kniebeugen braeuchte.

"Kommt darauf an." Was macht die Funktion denn? AFAICS wird in ein
gegebenes Verzeichnis über mehrere Ebenen gewechselt. Und wenn das nicht
geht, weil das Verzeichnis nicht existiert, wird solange gewartet, bis
die Datei existiert.

Das hat zwar nix mit ISO-C zu tun, aber bitte: Es werden hier noch
diverse andere konzeptionelle Unterschiede zwischen C und Pascal
benutzt, nämlich:

- C-Strings haben eine Ende-Markierung, Pascal-Strings ein Längen-Byte
- C hat einen Präprozessor

Übrigens ist es AFAICS unnötig, in Einzelschritten durch den
Verzeichnisbaum zu wechseln. Nötig ist es nur dann, wenn man noch
eli_wait_for_file() ausführen möchte. Mein »man« kennt diese Funktion
nicht, Google auch nicht, und auf tiefer gehende Recherchen habe ich
momentan keine Lust. D.h. in Pascal geht obiges mit:

uses sysutils;
begin
{usw. usf.}
chdir(path);
{usw. usf.}
end.

HTH,
Markus

Rainer Weikusat

unread,
Jun 30, 2009, 11:37:17 AM6/30/09
to
Markus Wichmann <null...@gmx.net> writes:
> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>> Ein Feld in C ist etwas vollkommen anderes als ein Feld in Pascal,
>> naemlich lediglich eine lueckenlose Folge von sequentiell allozierten
>> Objekten eines bestimmten Typs, die keinerlei Laufzeitidentitaet hat.
>
> Nanu? Das trifft auf Pascal doch ebenso zu.

Ein Pascal-Array ist (nach ISO-7185) als Funktion definiert: Es bildet
eine Definitionsmenge (dh den Typ bzw Untertyp 'gueltige Indices fuer
dieses Feld') auf eine Bildmenge (Menge unterschiedlicher Komponenten
identischen Typs) ab. Ob das in irgendeiner Weise unter Zuhilfename
von 'Speicher' eines Computer stattfindet, also zB durch traversieren
einer verketteten Liste, deren Elemente jeweils das Datenobjekt und
den zugehoerigen Indexwert enthalten, oder ob das ganze per Post an die
ETH Zuerich geschickt und dort ausgewuerfelt wird, darueber schweigt
sich der Text aus.

>> Zugriffe auf Feldelemente erfolgen ausschliesslich mit Hilfe von
>><Zeiger, Distanz>-Paaren. Logischerweise ist die Entfernung des ersten
>> Feldelementes vom Feldanfang 0.
>
> Das ist der Unterschied. Wobei... in Pascal muss man halt die Nummer des
> ersten Elementes kennen, dann ergibt sich der Abstand aus der Differenz
> des Feldindex und des Anfangselements.

Fast. Sie ergibt sich, in dem man die Ordinalwerte der beiden Indices
subtrahiert, dh die Ergebnisse von ord(). Aber das ist eigentlich
bloss eine fuer Zugriffe belanglose mathematisch Eigenschaft der Menge
der ganzen Zahlen.

> BTW: Ja, ich wei� das durchaus, aber dem OP schien es nicht klar zu


> sein, denn er wollte zur Allokation von CHAR_BITS+1 Zeichen ein Feld der

> Gr��e CHAR_BITS+2 anlegen.

Es schien, mit Verlaub, auch Dir nicht ganz klar zu sein. Das sich
manche C-Ausdruecke und manche Pascal-Ausdruecke aehnlich sehen,
bedeutet nichts darueber hinaus.

>> Damit geht dann zum Beispiel sowas:
>>
>> p = *path == '/' ? path + 1 : path;
>> while ((p = strchr(p, '/'))) {
>> *p++ = 0;
>>
>> rc = chdir(path);
>> if (rc == -1)
>> switch (errno) {
>> case ENOENT:
>> rc = eli_wait_for_file(path, file_created, NULL);
>> if (rc == ELI_WFF_ERROR) exit(1);
>>
>> rc = chdir(path);
>> rc != -1 || sys_die(__func__, "chdir");
>> break;
>>
>> default:
>> sys_die(__func__, "chdir");
>> }
>>
>> path = p;
>> }
>>
>> wofuer man in Pascal einiges an Kniebeugen braeuchte.
>
> "Kommt darauf an." Was macht die Funktion denn? AFAICS wird in ein

> gegebenes Verzeichnis �ber mehrere Ebenen gewechselt. Und wenn das nicht


> geht, weil das Verzeichnis nicht existiert, wird solange gewartet, bis
> die Datei existiert.
>
> Das hat zwar nix mit ISO-C zu tun, aber bitte:

Das hat sehr wohl etwas mit ISO-C zu tun: Ein 'C-String', dh eine
durch ein Nullbyte abgeschlossene Folge von Bytes mit einem von Null
verschiedenen Wert wird in Teil-Strings zerlegt, in dem der
Anfangszeiger ueber das Feld 'geschoben' wird. Das geht mit Pascal
nicht, hier muesste man mit dem Feld, dem Anfangs- und dem Endindex
hantieren.

[...]

> �brigens ist es AFAICS unn�tig, in Einzelschritten durch den
> Verzeichnisbaum zu wechseln. N�tig ist es nur dann, wenn man noch
> eli_wait_for_file() ausf�hren m�chte.

In der Tat.

0 new messages