Forum: Mikrocontroller und Digitale Elektronik Wie die Bytegröße einfach bestimmen (in C)?


von Erwin M. (nobodyy)


Lesenswert?

Ein Bekannter meint weil er einen 16-Bit-Mikrocontroller verwendet und 
daran einen 16-Bit-Datenbus hat sind bei ihm die Bytes alle 16 Bit groß.
Der C-Standard (C99) sagt dazu nur "A byte is composed of a contiguous 
sequence of bits, the number of which is implementation-defined.", so 
das es prinzipiell möglich wäre.

Deshalb habe ich nachgesehen mit

(*(volatile uint32_t*)(1234)) = 0x00000000;
(*(volatile uint16_t*)(1234)) = 0xaaaa;
first_byte  = (*(volatile uint8_t*)(1234))
second_byte = (*(volatile uint8_t*)(1235))

und es zeigte sich das 16-Bit-Werte sich über zwei Bytes erstrecken, 
also ein Byte auch dort 8 Bit hat, weil first_byte und second_byte den 
Wert 0xaa haben (und die zwei nachfolgenden Bytes Null sind).
Trotzdem stellen sich zwei Fragen:

Wie kann man die Bytegröße (in Bit) automatisch bestimmen; hat jemand 
eine fertige C-Funktion oder ein Makro dafür?

Gibt es überhaupt ein Beispiel für eine Plattform mit C-Compiler, auf 
der ein Byte ungleich 8 Bit hat und wenn ja, findet man das auch 
außerhalb von Museen?
Wenn ja, dann wäre C ja sehr wenig portabel, denn es gibt daneben ja 
noch die plattformabhängige Endianess.

von Karl H. (kbuchegg)


Lesenswert?

Erwin Meyer schrieb:

> Wie kann man die Bytegröße (in Bit) automatisch bestimmen;

gar nicht.
Im Header Limits.h gibt es eine Konstante CHAR_BIT, die sagt es dir

Wobei das genaugenommen nicht das ist wonach du fragst. Es handelt sich 
um die Anzahl der Bits in einem char. Üblicherweise ist ein char (bzw 
unsigned char) in C gleichzusetzen mit einem "Byte", in dem Sinne als es 
der kleinste Datentyp ist, den du integral ansprechen kannst.

Per Defintion hat ein Byte in C mindestens 8 Bit. Auf einem System, 
welches CHAR_BIT gleich 16 hat, besteht ein char dann eben aus 2 8-Bit 
Byte. Allerdings ist auch auf solchen Systemen der sizeof(char) gleich 
1, sodass man aus C-Sicht ein C-Byte als 16-Bit Einheit ansehen könnte 
obwohl es im Speicher meistens aus 2 8-Bit Bytes zusammengebaut wird. 
Heutige Speicher und Bussysteme sind als Vielfaches von 8 auf den 
Datenleitungen aufgebaut.

von Albert .. (albert-k)


Lesenswert?

Dein Freund meint wahrscheinlich das ein integer 16 bit groß ist. Das 
war nämlich wirklich historisch so das die größe eines Int mit der 
breite des Datenbusses skaliert war. Der bruch kam dann erst bei 
Einführung der 64bit Systeme.
Ein Byte hingegen kenne ich überall nur als 8bit groß (wenn man mal von 
historischen ausnahmen, die aber nicht mehr verwendet weren, absieht).

Die größe eines Int kannst du bestimmen indem du mal in limits.h (wenn 
es verfügbar ist) reinschaust. Dort stehen die maximalen Werte für 
unsigned Variablen.
Ansonsten würe ich ein long int als Zählvariable nehmen und dann 
parallel ein int solange hochzählen bis es zum überlauf kommt und 
schauen welcher wert in meinem long steht.

von (prx) A. K. (prx)


Lesenswert?

Erwin Meyer schrieb:

> Gibt es überhaupt ein Beispiel für eine Plattform mit C-Compiler, auf
> der ein Byte ungleich 8 Bit hat, und wenn ja, findet man das auch
> außerhalb von Museen?

Was sich heute noch findet sind Maschinen, die nicht durchweg Bytes 
adressieren, sondern ggf. Worte, und folglich das Byte als Grundeinheit 
der Adressierung nicht existiert. Zumindest anfangs bot sich das bei 
DSPs an, wie es da heute aussieht weiss ich aber nicht.

Ein ziemlicher Exot ist der recht neue MaxQ2000. Der adressiert 8-Bit 
Bytes wenn man Bytes meint und 16-Bit Worte wenn man Worte meint. Die 
Adresse des ersten Bytes eines Wortes ist also das doppelte der Adresse 
des Wortes. Und weil das eine 16-Bit Architektur ist lässt sich nur die 
erste Hälfte des Adressraumes als Bytes adressieren. Ich kann mir 
angenehmeres vorstellen, als ausgerechnet dafür einen C Compiler zu 
basteln - gibt es aber. Da wird jeder pointer type cast zum Alptraum.

Früher gab es beispielsweise 36-Bit und 60-Bit Maschinen, die ganze oder 
halbe Worte adressierten. Ein natürliches Byte gab es da nicht, auch 
keine Befehle dafür, und da diese Kisten nur für Berechnungen da waren 
hat man gerne 6-Bit Zeichensätze verwendet und auf Kleinschreibung 
verzichtet. Zeichenverarbeitung fand entweder wortweise statt und wenn 
man partout an einzelne Zeichen eines Strings ran wollte, dann musste 
notfalls dividiert werden. Den 60-Bittern hat man bald auch alternativ 
8-Bit Bytes zugemutet - man hätte sich da also beide Varianten aussuchen 
können. Von einem C Compiler auf solch einer Kiste ist mir aber nichts 
bekannt, deren Zeit war abgelaufen als C populär wurde.

> Wenn ja, dann wäre C ja sehr wenig portabel, denn es gibt daneben ja
> noch die plattformabhängige Endianess.

Die Endianess ist ein weitgehend sprachunabhängiges Problem. Sobald man 
binär codierte Datenstrukturen austauscht hat man eine Konvention am 
Hals. Egal in welcher Sprache. Da die network byte order big-endian ist 
und die meisten Maschinen heute little-endian sind hat man das Problem 
auch sozusagen festgeschrieben.

von Erwin M. (nobodyy)


Lesenswert?

Also ich formuliere es hoffentlich klarer hiermit: Wieviel Bits liegen 
an einer Adresse, und nur unter dieser einen?

Wenn ich einen Speicherbereich über memset mit 0x00 fülle, wieviele (auf 
binär 1 gesetzte) Bits muss ich dann an eine Speicherstelle schreiben, 
bis die Bits auch in irgendeine andere Speicherstelle geraten?

Der Standard bietet ja Datentypen wie uint8_t, mit dennen man nachmessen 
kann.


Karl Heinz Buchegger schrieb:

> Im Header Limits.h gibt es eine Konstante CHAR_BIT, die sagt es dir.

Das passt nicht ganz: Der verwendete Compiler von Keil hat mit C99 nur 
entfernt zu tun; es ist ein prä-C90-Kompiler, und zudem geht es nicht um 
die Größe eines Bytes mit dem der C-Code arbeitet, z. B. in Form von 
char-Variablen, sondern die Größe eines Bytes im Speicher, den der Code 
verwendet. Das sind ja zwei ganz verschiedene Sachen meint der Bekannte.
Daneben gibt es auch noch eine dritte Sorte Bytes und zwar die 
Speicherworte, die bei einem 16-Bit-Datenbus tatsächlich 16 Bit haben. 
Bei der C-Programmierung ist das aber egal, außer bei Performance- und 
Alignment-Fragen.

von slw (Gast)


Lesenswert?

wie lange byte, int oder long ist, läßt sich aus der 
Compilerbeschreibung ergründen und nur dort:)

von (prx) A. K. (prx)


Lesenswert?

Erwin Meyer schrieb:

> Also ich formuliere es hoffentlich klarer hiermit: Wieviel Bits liegen
> an einer Adresse, und nur unter dieser einen?

Also formuliere ich es hoffentlich klarer hiermit: Beim MaxQ2000 hängt 
es davon ab, ob du grad mit Bytes oder mit Worten arbeitest. Bei Bytes 
sind es 8 und bei Worten sind es 16, da sich die Adresse zweier 
aufeinander folgender Bytes ebenso wie die Adresse zweier aufeinander 
folgender Worte nur um 1 unterscheidet und nicht jeder Teil des 
Datenspeichers für Bytes verwendbar ist.

M.a.W: Es gibt bei diesem auch in anderer Hinsicht sehr schrägen Vogel 
keine universelle Adresskonvention, also lässt sich die Frage nicht 
eindeutig beantworten.

von Achim M. (minifloat)


Lesenswert?

Weil auf verschiedenen Maschinen die Größe des int immer anders ist, hab 
ich mir das hier angewöhnt:
1
#include <inttypes.h>
2
3
uint8_t meine_8bit_unsigned_variable;
4
int16_t meine_16bit_signed_variable;

Seitdem kämpfe ich nicht mehr mit Abbruchkriterien von Schleifen und 
Bedingungen, nur weil irgendwie da oben nochmal soviel Bits dranhängen, 
als ich mir gedacht hab'(und eines davon aus unerwünschtem Grund 1 ist).
Macht den Code obendrein angenehmer lesbar.
Dieses Runter-ver-&-en mit 0xFF und Herum-cast-en muss nicht sein.

mfg mf

von Erwin M. (nobodyy)


Lesenswert?

A. K. schrieb:
> Ein ziemlicher Exot ist der recht neue MaxQ2000. Der adressiert 8-Bit
> Bytes wenn man Bytes meint und 16-Bit Worte wenn man Worte meint. Die
> Adresse des ersten Bytes eines Wortes ist also das doppelte der Adresse
> des Wortes. Und weil das eine 16-Bit Architektur ist lässt sich nur die
> erste Hälfte des Adressraumes als Bytes adressieren. Ich kann mir
> angenehmeres vorstellen, als ausgerechnet dafür einen C Compiler zu
> basteln - gibt es aber. Da wird jeder pointer type cast zum Alptraum.

Dann ist die Programmiersprache aber kein C, denn wenn ich einem Objekt 
einen Wert zuweise oder auslese ist das in C unabhängig davon ob es mit 
einem 8- oder 16-Bit-Zugriff oder sonstwie geschieht, bespielsweise beim 
Verwenden von memcpy, das ja 8- wie 16-Bit-Werte verwenden kann.
Die Hardware kann ja rumrechchnen wie sie will, aber der Compiler hat 
dafür zu sorgen das Unterschiede zwischen 8- und 16-Bitadressierung 
transparent sind, sich also nicht auf den C-Code auswirken können. Sonst 
könnte man ja gleich in Assembler programmieren.

von (prx) A. K. (prx)


Lesenswert?

Erwin Meyer schrieb:

> Dann ist die Programmiersprache aber kein C

Ich beschrieb die Maschine, nicht die Implementierung eines Compilers.

Du selbst schriebst ja auch: "und zudem geht es nicht um die Größe eines 
Bytes mit dem der C-Code arbeitet, z. B. in Form von char-Variablen, 
sondern die Größe eines Bytes im Speicher".

Und damit reduziert es sich auf die Frage, wie gross ein Byte in einem 
Speicher ist, der keine Bytes kennt (bzw. nicht überall). Eine Antwort 
darauf kennt allenfalls der Compiler, nicht der Speicher.

von Achim M. (minifloat)


Lesenswert?

Erwin Meyer schrieb:
> Sonst könnte man ja gleich in Assembler programmieren.

Ist der Grund, warum sich viele Menschen beim AVR gleich für ASM 
entscheiden ;-)

von Erwin M. (nobodyy)


Lesenswert?

A. K. schrieb:
> Erwin Meyer schrieb:
>
>> Also ich formuliere es hoffentlich klarer hiermit: Wieviel Bits liegen
>> an einer Adresse, und nur unter dieser einen?
>
> Also formuliere ich es hoffentlich klarer hiermit: Beim MaxQ2000 hängt
> es davon ab, ob du grad mit Bytes oder mit Worten arbeitest. Bei Bytes
> sind es 8 und bei Worten sind es 16, da sich die Adresse zweier
> aufeinander folgender Bytes ebenso wie die Adresse zweier aufeinander
> folgender Worte nur um 1 unterscheidet und nicht jeder Teil des
> Datenspeichers für Bytes verwendbar ist.

Also selbst wenn es sowas gibt, ist die Antwort meine Frage auch hier 
klar: Bei mehr als 9 Bit zeigen sich Bits auch an einer anderen Adresse 
und damit ist beispielsweise ein Speicherbereich von 0x1000 bis 0x2000 
mit memset(0, 0, 0x1000) zu initialisieren, ganz egal ob das über 8- 
oder 16-Bit-Zugriffe erfolgt.

von (prx) A. K. (prx)


Lesenswert?

Erwin Meyer schrieb:

> Also selbst wenn es sowas gibt, ist die Antwort meine Frage auch hier
> klar: Bei mehr als 9 Bit zeigen sich Bits auch an einer anderen Adresse

Eben nicht. Die zweite Hälfte des Datenadressraums kennt keine Adressen 
von 8-Bit Objekten, sondern nur Adressen von 16-Bit Objekten. An der 
(Wort-) Adresse 0x8000 kann sich der Wert 0x1111 befinden und an der 
Adresse 0x8001 der Wert 0x2222. Folglich zeigen sich dort erst ab 17 
Bits welche an der nächsten Adresse.

Definiert man "Byte" als kleinste mit einer eindeutigen Adresse 
versehenden Einheit eines Speichersystems, dann ist das Byte in der 
ersten Hälfte des Datenraums 8 Bits und in der zweiten Hälfte 16 Bits 
gross. ;-)

Dass Maxim natürlich trotzdem von 8-Bit Bytes redet und sich die Sache 
in C sicherlich etwas anders darstellt als auf der Hardwareebene ist ein 
anderes Thema.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Albert ... schrieb:
> Das
> war nämlich wirklich historisch so das die größe eines Int mit der
> breite des Datenbusses skaliert war. Der bruch kam dann erst bei
> Einführung der 64bit Systeme.

Kennt jemand irgendeine real existierende C-Implementierung, bei der die 
Größe eines int kleiner ist als 16 Bit?

von (prx) A. K. (prx)


Lesenswert?

Rufus Τ. Firefly schrieb:

> Kennt jemand irgendeine real existierende C-Implementierung, bei der die
> Größe eines int kleiner ist als 16 Bit?

Da C für "int" mindestens 16 Bits vorschreibt...

Was es definitiv gibt: Compiler, die die berüchtigte Regel, dass alle 
Rechnungen vom Ergebnis her mindestens in "int" durchzuführen seien, nur 
optional beherzigen. Das ist bei allen Architekturen mit ausschliesslich 
einem 8-Bit Akkumulator auch naheliegend, wenngleich nicht konform zum 
Standard.

von (prx) A. K. (prx)


Lesenswert?

Albert ... schrieb:

> Dein Freund meint wahrscheinlich das ein integer 16 bit groß ist. Das
> war nämlich wirklich historisch so das die größe eines Int mit der
> breite des Datenbusses skaliert war. Der bruch kam dann erst bei
> Einführung der 64bit Systeme.

Das war schon vor 30 Jahren anno 68000 nicht mehr so eindeutig. Denn da 
gab es für den exakt gleichen Prozessor sowohl C-Compiler mit 16-Bit int 
als auch welche mit 32-Bit int.

Warum 16 Bits: schneller, weil 16-Bit ALU und Datenbus.

Warum 32 Bits: Adressbreite, damit Portabilität von Code, der diese 
Identität voraussetzt. Gabs damals anno K&R-C ohne Prototypes oft.

von Erwin M. (nobodyy)


Lesenswert?

A. K. schrieb:
>
> Warum 32 Bits: Adressbreite, damit Portabilität von Code, der diese
> Identität voraussetzt. Gabs damals anno K&R-C ohne Prototypes oft.

Also für Portabilität gibt es Datentypen wie int32_t, die exakt 32 Bit 
groß sind.
Das es Compiler gibt die ANSI-C nicht kennen und folglich auch int32_t 
nicht haben ist eine andere Geschichte, insbesondere bei Firmen wie IAR 
und Keil, aber wenn ich von C schreibe, dann meine ich ANSI-C und der 
einzige derzeit gültige Standard dafür ist C-99, weil jeder neue 
Standard die vorherigen für ungültig erklärt, allein schon um 
Mehrdeutigkeit auszuschließen.

Übrigens habe ich einen anderen internationalen Standard gefunden, der 
ein Byte genau beschreibt: In IEC 60027-2 ist ein Byte ein Oktet von 
Bits, enthält also genau 8 Bit.

von Erwin M. (nobodyy)


Lesenswert?

A. K. schrieb:
> Erwin Meyer schrieb:
>
>> Also selbst wenn es sowas gibt, ist die Antwort meine Frage auch hier
>> klar: Bei mehr als 9 Bit zeigen sich Bits auch an einer anderen Adresse
>
> Eben nicht. Die zweite Hälfte des Datenadressraums kennt keine Adressen
> von 8-Bit Objekten, sondern nur Adressen von 16-Bit Objekten.

Die Frage war nicht abhäng vom Adressraum, so das ein Test aller 
Adressen auf der erwähnten Plattform ergibt das das kleinste Objekt 8 
Bit enthält.

von (prx) A. K. (prx)


Lesenswert?

Erwin Meyer schrieb:

> Also für Portabilität gibt es Datentypen wie int32_t, die exakt 32 Bit
> groß sind.

Die erwähnte Portabilität bezog sich auf die Identität der Grösse von 
Pointern und "int", nicht auf "int" und 32 Bits. Auch das lässt sich 
machen, aber darum ging es nicht.

Mir ist bekannt, dass dieses Thema heute keines mehr ist, aber die Story 
bezog sich ausdrücklich auf 68000 Anfang der 80er als es weder den 
vordefinierten Typ int32_t noch ANSI-C noch Parameterdeklarationen 
ausserhalb der Funktionsdefinition gab. Damals war das relevant.

Das war überdies nur eine Replik auf Alberts These, dass sich erst bei 
64-Bit Architekturen eine Schere zwischen Datenbusbreite und int ergeben 
hätte. Nope, das gab es schon viel früher.

von Christian H. (christian_h)


Lesenswert?

Ein Byte hat die Größe 8 Bit erhalten, da sich dadurch mit 7 Bit ASCII 
darstellen ließe + 1 Parity-Bit. Deswegen sind es 8 Bit.

von (prx) A. K. (prx)


Lesenswert?

Erwin Meyer schrieb:

> und Keil, aber wenn ich von C schreibe, dann meine ich ANSI-C und der
> einzige derzeit gültige Standard dafür ist C-99, weil jeder neue
> Standard die vorherigen für ungültig erklärt, allein schon um
> Mehrdeutigkeit auszuschließen.

M.a.W: Mindestens die meisten real existierenden C Compiler sind keine C 
Compiler, sondern Hochstapler und dürften sich folglich nicht so nennen, 
GCC eingeschlossen?

Mal andersrum gefragt: Gibt es dieser Definition gemäss überhaupt einen 
C Compiler, der sich so nennen darf, weil er deinem Anspruch 
vollständiger Konformität zu C99 gerecht wird?

Apropos: Ich weiss grad nicht, ob C99 wirklich alte Versionen von C für 
ungültig erklärt, aber etliche andere mir bekannte Standards sind 
versioniert, d.h. die Mehrdeutigkeit wird dadurch ausgeschlossen, dass 
die Version des Standards genannt wird. Würden neue Standards alte stets 
für ungültig erklären, dann müsste mit Verabschiedung eines neuen 
Standards die komplette bezügliche Industrie schlagartig solange den 
Betrieb einstellen, bis neue Produkte auf dem Markt sind, weil die 
bisherige Bezeichnung nur noch für die neuen Produkte zulässig sei. 
Grotesk.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rufus Τ. Firefly schrieb:
> Kennt jemand irgendeine real existierende C-Implementierung, bei der die
> Größe eines int kleiner ist als 16 Bit?

Mit avr-gcc -mint8 ist sizeof(int) = 1, allerdings wird diese Option 
nicht mehr gepflegt und ist in neueren Versionen spätestens ab 4.6 nicht 
mehr funktional.

Um das "live" zu sehen, braucht mal also eine was angestaubte Version 
von avr-gcc.

von Klaus (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Ein Bekannter meint weil er einen 16-Bit-Mikrocontroller verwendet und
> daran einen 16-Bit-Datenbus hat sind bei ihm die Bytes alle 16 Bit groß.

Wiki sagt dazu:

Das Byte [baɪt] ist ein Mengenbegriff (Maßeinheit) in der Digitaltechnik 
und der Informatik, der für eine Zusammenstellung aus mehreren Bit 
steht, im Allgemeinen für eine Anzahl von 8.

Das hat nichts mit einem Prozessor oder einem Compiler zu tun, sondern 
nur mit binärer Mathematik. Obwohl da steht "im Allgemeinen für eine 
Anzahl von 8", hab ich noch nie etwas anderes gesehen. Um binär zu 
rechnen, brauche ich keinen Computer, da tuns auch Papier und Bleistift.

Dein Bekanter sollte auf einen 8-Bit-Mikrocontroller umsteigen, 
ansonsten ist für ihn ein 1KB Ram nur 512 Bytes groß ;-)

MfG Klaus

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.