mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Kleines C-Prog geht nicht


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: HH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen,
brauche mal eure Hilfe bei einem kleinen Syntax-Fehler. Hier mal der 
Code:

int main(void)
{
   DDRA = 0x0F;
   while(1)
  {
    PORTA = 3;
    _delay_ms(500);
    PORTA &= (0<<PA0);
    _delay_ms(500);
  }
}

LED an Port A.0 blinkt ordnungsgemäß wie erwartet nur die LED A.1 blinkt 
gleichzeitig mit. Sie dürfte eigentlich mit der LED an A.0 an gehen und 
dann nicht mehr ausgehen.
Verwende gerade das Studio 6.2 mit dem internen C-Compiler. Warum wird 
überhaupt ein Schiebebefehl verwendet um Ports zu schalten? Bei BASCOM 
ist es doch so einfach. Habe aber gerade eine zeitkritische Anwendung.
Danke HH

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HH schrieb:
> PORTA &= (0<<PA0);
Was willst du damit bezwecken? Erkläre es mal Schritt für Schritt....

Autor: A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int main(void)
{
   DDRA = 0x0F;
   while(1)
  {
    PORTA |= 3;
    _delay_ms(500);
    PORTA &= ~3;
    _delay_ms(500);
  }
}

Finde die Unterschiede und versuche sie selbststständig zu verstehen!

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HH schrieb:
> brauche mal eure Hilfe bei einem kleinen Syntax-Fehler

Da es kompiliert ist es offensichtlich kein Syntax-Fehler... Überleg 
doch mal genau was (0 << PA0) für einen Wert hat.

Autor: Ähhmm Ja (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
HH schrieb:
> Habe aber gerade eine zeitkritische Anwendung.

HH schrieb:
> _delay_ms(500);

Autor: HH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja mit

PORTA &= ~(1<<PA0); funktioniert es und mit
PORTA = ~(1<<PA0); blinken die LEDs 0 und 2,3,4,5,6,7 abwechselnd. 3 
bleibt ein!
Trinke erst mal einen Kräuter!
Danke

Autor: Curby23523 N. (nils_h494)
Datum:

Bewertung
-5 lesenswert
nicht lesenswert
ICh weiß ja nicht welchen Controller du verwendest. Eigentlich sollte
    PORTA = 3;
    _delay_ms(500);
    PORTA &= (0<<PA0);
    _delay_ms(500);

funktionieren. Möglicherweise liegt so etwas vorkonfiguriertes wie JTAG 
auf dem Pin?

: Bearbeitet durch User
Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int main(void)
{
   DDRA  |= (1<<PA1)|(1<<PA0);
   PORTA |= (1<<PA1)|(1<<PA0);

   while(1)
   {
    PINA = (1<<PA0);
    _delay_ms(500);
   }
}


Funktioniert mit allen etwas moderneren AVR.
z.B. ATTiny85 ATMega328p

Autor: HH (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo Curby,
dachte auch dass PORTA &= (0<<PA0); funktioniert und nur A.0 
ausschaltet.
Aber eben nur der Befehl PORTA &= ~(1<<PA0); funktioniert. Dann mache 
ich es eben so. ;-(
Habe einen Tiny461A dran.

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HH schrieb:
> dachte auch dass PORTA &= (0<<PA0); funktioniert und nur A.0
> ausschaltet.

Wieso?

irgendwas & null, ist null

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HH schrieb:
> Dann mache ich es eben so.
Ich hatte den Tipp mit dem Nachdenken über den < Operator gegeben. Du 
solltest ihn befolgen, denn solche Bitoperationen werden dir laufend 
begegnen.

Ein Tipp dazu: PA0 ist in einem  Headerfile definiert als 0

: Bearbeitet durch Moderator
Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HH schrieb:
> Habe einen Tiny461A dran.
Der ist modern genug!
Toggeln mit "PINA = (1<<PA0);" also möglich.

: Bearbeitet durch User
Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Curby23523 N. schrieb:
> Eigentlich sollte    PORTA = 3;
>     _delay_ms(500);
>     PORTA &= (0<<PA0);
>     _delay_ms(500);
>
> funktionieren.

Aha.

Schon HH schrieb, dass es nicht funktioniert. Das gibt dir nicht zu 
Denken ?

Autor: M. K. (sylaina)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Curby23523 N. schrieb:
> ICh weiß ja nicht welchen Controller du verwendest. Eigentlich sollte
>
>     PORTA = 3;
>     _delay_ms(500);
>     PORTA &= (0<<PA0);
>     _delay_ms(500);
> 
>
> funktionieren. Möglicherweise liegt so etwas vorkonfiguriertes wie JTAG
> auf dem Pin?

Klar funktioniert das, deshalb Compiliert das auch ohne Fehler. Aber 
auch für dich, überlege mal was
PORTA &= (0<<PA0)

Bewirken wird. Grade ein Anfänger wird das falsch interpretieren ;)

: Bearbeitet durch User
Autor: HH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Irgendwie bewirkt der Befehl:
PORTA &= (0<<PA0);
dass der gesamte PORTA mit Null überschrieben wird und nicht nur PA.0!
Mache mal Pause ......
Danke für die Hinweise!

Autor: M.K. B. (mkbit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich gehe mal davon aus, dass du als Anfänger etwas auf dem Schlauch 
stehst.
Hier mal die Hausaufgabe fürs Wochenende:
PORTA &= (0<<PA0)

Überleg mal was die Einzelschritte im folgenden ergeben. Ob die 
Datentypen stimmen, kann ich nicht sagen, aber es geht ums Prinzip:
uint x = (0<<PA0);
PORTA = PORTA & x;

Ich denke es hilft dir viel, wenn du deinen Denkfehler selber erkennst.
Mir hat zum Einstieg das gcc Tutorial hier gut geholfen (Verändern von 
Registerinhalten).
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ver.C3.A4ndern_von_Registerinhalten

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
4 lesenswert
nicht lesenswert
Bitmanipulation ist hier Pflichtlektüre.

Autor: Joachim B. (jar)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
HH schrieb:
> Irgendwie bewirkt der Befehl:
> PORTA &= (0<<PA0);
> dass der gesamte PORTA mit Null überschrieben wird und nicht nur PA.0!

schreibe dir es doch einfach auf:

PA0 ist Bit 0

also setzt du die 8 Portsbits auf 0000 0000
Es ist Bit 0 auf 0 gesetzt richtig aber auch Bit 1 bis 7

und nun undierst du alle Bits auf Port A mit 0
was soll da rauskommen ausser 8x NULL?
Maske 0000 0000
PortA 1010 xxxx
---------------
gibt 0000 0000

weswegen wird es wohl richtig mit
PORTA &= ~(1<<PA0)
Maske 0000 0001
negiert 1111 1110
PortA 1010 xxxx
---------------
gibt 1010 xxx0

gemacht?

alle bleiben wie sie sind ausser BIT 0 das wird auf 0 gesetzt gelöscht

Autor: Curby23523 N. (nils_h494)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HH schrieb:
> LED an Port A.0 blinkt ordnungsgemäß wie erwartet nur die LED A.1 blinkt
> gleichzeitig mit. Sie dürfte eigentlich mit der LED an A.0 an gehen und
> dann nicht mehr ausgehen.

MaWin schrieb:
> Schon HH schrieb, dass es nicht funktioniert. Das gibt dir nicht zu
> Denken ?

Ja, wieder zu schnell gelesen, er möchte, dass der PORT nicht angeht. 
Dann bitte in C-Lektüre nachschauen, wie man Bits manipuliert.

Autor: c-hater (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
HH schrieb:

> Trinke erst mal einen Kräuter!

Entweder Programmieren oder Saufen. Beides gleichzeitig funktioniert 
eher nicht, da wirst du nur das Saufziel erreichen...

Geringe Mengen Alkohol können allerdings wirklich auch die Kreativität 
beim Programmieren erhöhen, so meine Beobachtung. Sie lösen etwas die 
Verhaftung in eingefahrene Bahnen.

> Warum wird
> überhaupt ein Schiebebefehl verwendet um Ports zu schalten? Bei BASCOM
> ist es doch so einfach.

Zum Beispiel solche Veklemmungen... Nein, hier wird kein Schiebebefehl 
verwendet. Geschoben wird hier nur zur Compile-Zeit, letztlich ergeben 
die Ausdrücke zur Laufzeit eine konstante Zahl.

Du solltest dich mit dem grundsätzlichen Unterschied zwischen 
Kompilezeit und Laufzeit auseinandersetzen. Wenn du den begriffen hast, 
wird das klarer.

Autor: HH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh c-hater. Auch schon getrunken?

Mir ist jetzt schon klar, wie es funktioniert. Werde aber wohl nicht 
erfahren, warum Mann einen schlüssigen Befehl, um ein Bit zusetzen (also 
mit Oder maskiert - mit oder ohne senkrechten Strich) nicht eine 
ähnliche Syntax verwendet, um ein Bit zu löschen. In Bascom und in 
Pascal für PICs geht es doch. Aber hier wird erst das Einer-Komplement 
mit der Tilde gebildet.
Oder seht euch mal CodeVision an.
Aber die Variante von A (Gast) ganz oben gefällt mir ganz gut.

Danke und schönen Sonntag noch.

Autor: Karl M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

kennst Du schon die Funktionalität von sbit.h (peda - Peter Dannegger)?

Hier die Includedatei:
https://www.mikrocontroller.net/attachment/58294/SBIT.H

Beispiel:
#include "sbit.h"
#define LED0 SBIT(PORTA,PA0)

// schreibt man einfach:
LED = 0;
LED = 1;

Autor: HH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja. Der Typ ist gut und sachlich.
In den anderen Sprachen verwende ich auch ganz gern alias-Namen.

Sitze Im Biergarten und der Akku .....

Danke.

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
HH schrieb:
> Mir ist jetzt schon klar, wie es funktioniert. Werde aber wohl nicht
> erfahren, warum Mann einen schlüssigen Befehl, um ein Bit zusetzen (also
> mit Oder maskiert - mit oder ohne senkrechten Strich) nicht eine
> ähnliche Syntax verwendet, um ein Bit zu löschen. In Bascom und in
> Pascal für PICs geht es doch. Aber hier wird erst das Einer-Komplement
> mit der Tilde gebildet.
> Oder seht euch mal CodeVision an.


Ich bin mir nicht sicher, ob du mit dieser Einstellung in der C und C++ 
Welt gut aufgehoben bist.

Denn da wird nicht alles mundgerecht vorgekaut, wie es deiner Meinung 
nach sein sollte. Hier muss man die die Dinge selber machen.

HH schrieb:
> Aber die Variante von A (Gast) ganz oben gefällt mir ganz gut.
Passt ins Bild.

: Bearbeitet durch User
Autor: NaJa (Gast)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
Es ist fast wie immer. Einige sachliche Antworten und viele am Kern 
vobei.
Anfängern oder besser hier > Umsteigern < wird unterstellt, dass sie es 
besser lassen sollten.

Ja, Arduino F, vielleicht bist Du in diesem Forum falsch mit Deiner 
Einstellung. Deine Beiträge an anderer Stelle "passen ins Bild"!

Also weiter so .....

Autor: Sven A. (quotschmacher)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Arduino F. schrieb:
>
> int main(void)
> {
>    DDRA  |= (1<<PA1)|(1<<PA0);
>    PORTA |= (1<<PA1)|(1<<PA0);
> 
>    while(1)
>    {
>     PINA = (1<<PA0);
>     _delay_ms(500);
>    }
> }
> 

was spricht denn dagegen? das steht sogar im datenblatt der controller, 
bei denen es möglich ist, das man so den pin toggled.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HH schrieb:
> Oh c-hater. Auch schon getrunken?
>
> Mir ist jetzt schon klar, wie es funktioniert.

Das glaube ich nicht.

> Werde aber wohl nicht erfahren, warum Mann einen schlüssigen Befehl, um
> ein Bit zusetzen (also mit Oder maskiert - mit oder ohne senkrechten
> Strich) nicht eine ähnliche Syntax verwendet, um ein Bit zu löschen.

Weil das nicht primär die "Befehle" sind, um ein Bit zu setzen oder zu 
löschen. Sie werden nur unter anderem auch dafür verwendet.

Autor: M. K. (sylaina)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven A. schrieb:
> was spricht denn dagegen? das steht sogar im datenblatt der controller,
> bei denen es möglich ist, das man so den pin toggled.

Dass du das "^" vergessen hast vor dem "=" ;)

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
M. K. schrieb:
> Dass du das "^" vergessen hast vor dem "=" ;)

Nein, hat er nicht. Bei halbwegs aktuellen AVRs kann man ein Bit in 
einem PORT-Register toggeln, indem man eine 1 in das entsprechende Bit 
des dazugehörigen PIN-Registers schreibt.

Sven A. schrieb:
> was spricht denn dagegen?

Mir würde nur einfallen, dass es bei Portierung auf einen älteren AVR zu 
fiesen, schwer zu findenden Fehlern kommen könnte.

: Bearbeitet durch User
Autor: Karl M. (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
M. K. schrieb:
> Dass du das "^" vergessen hast vor dem "=" ;)

Sorry, die Anweisung an PINx! ist schon ok, man findet diese Eigenschaft 
zum Toggeln eines Bits bei "neueren" Amtel µC nur versteckt im 
Datenblatt.
PINx = (1<<Pn0);

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arduino F. schrieb:
> HH schrieb:
>> Mir ist jetzt schon klar, wie es funktioniert. Werde aber wohl nicht
>> erfahren, warum Mann einen schlüssigen Befehl, um ein Bit zusetzen (also
>> mit Oder maskiert - mit oder ohne senkrechten Strich) nicht eine
>> ähnliche Syntax verwendet, um ein Bit zu löschen. In Bascom und in
>> Pascal für PICs geht es doch. Aber hier wird erst das Einer-Komplement
>> mit der Tilde gebildet.
>> Oder seht euch mal CodeVision an.
>
>
> Ich bin mir nicht sicher, ob du mit dieser Einstellung in der C und C++
> Welt gut aufgehoben bist.

Die eigentliche Frage ist doch (und die finde ich berechtigt):

Warum benötige ich zur Manipulation einzelner Bits einen Datentyp 
uint8_t, der ja vorzeichenlose Ganzzahlen repräsentieren soll?

Was er möchte ist ein Datentyp, der einfach nur eine Ansammlung von Bits 
darstellt, und der dann Operationen zum Setzen / Löschen einzelner Bits 
anbietet.

Und da ist er doch in der C++-Welt sehr gut aufgehoben ;-) Damit könnte 
man auch die Problematik des RMW lösen ...

Autor: Anderer Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Warum benötige ich zur Manipulation einzelner Bits einen Datentyp
> uint8_t, der ja vorzeichenlose Ganzzahlen repräsentieren soll?
> Was er möchte ist ein Datentyp, der einfach nur eine Ansammlung von Bits
> darstellt, und der dann Operationen zum Setzen / Löschen einzelner Bits
> anbietet.
> Und da ist er doch in der C++-Welt sehr gut aufgehoben ;-) Damit könnte
> man auch die Problematik des RMW lösen ...

Dir steht es natürlich frei eine Bitstruct darüber zu legen. Der 
Compiler muss trotzdem einen Zugriff auf das Register machen, das bei 
diesem Controller funktioniert. Das wird hier eben 8 Bit sein.
Wobei es bei manchen uC auch Bereiche gibt die Bit adressiert sind.

Autor: Karl M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Wilhelm M. schrieb:
> Warum benötige ich zur Manipulation einzelner Bits einen Datentyp
> uint8_t, der ja vorzeichenlose Ganzzahlen repräsentieren soll?

Die Frage ist doch schnell beantwortet, da ein Port eines AVR µC 8 Bit 
Breit ist.
Das "soll" ist doch eher ein "ist".
Und wenn in "C" programmiert wird, dann kann man sich seine eigenen 
Zugriffe auf Pins basierend auf einem Port programmieren, so dass einem 
die Syntax zusagt.

Hier geht es wirklich nur um das Aussehen, um mehr nicht.
Also warum der ganze Stress?

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anderer Frank schrieb:
> Wilhelm M. schrieb:
>> Warum benötige ich zur Manipulation einzelner Bits einen Datentyp
>> uint8_t, der ja vorzeichenlose Ganzzahlen repräsentieren soll?
>> Was er möchte ist ein Datentyp, der einfach nur eine Ansammlung von Bits
>> darstellt, und der dann Operationen zum Setzen / Löschen einzelner Bits
>> anbietet.
>> Und da ist er doch in der C++-Welt sehr gut aufgehoben ;-) Damit könnte
>> man auch die Problematik des RMW lösen ...
>
> Dir steht es natürlich frei eine Bitstruct darüber zu legen.

Ja, das mache ich auch schon sehr lange so ... und mittlerweile ist so 
etwas in rudimentärer Form (eine Ansammlung von Bits) auch in der 
libstdc++ enthalten ;-)

Autor: Markus F. (mfro)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C hat Bitfelder.

Ja, die sind implementation defined.

Na und?

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl M. schrieb:
> Hallo Wilhelm M. schrieb:
>> Warum benötige ich zur Manipulation einzelner Bits einen Datentyp
>> uint8_t, der ja vorzeichenlose Ganzzahlen repräsentieren soll?
>
> Die Frage ist doch schnell beantwortet, da ein Port eines AVR µC 8 Bit
> Breit ist.

8-Bit als ein Byte zusammengefasst: ja.

Aber diese 8-Bit immer als Ganzzahl interpretieren: klares nein.

> Hier geht es wirklich nur um das Aussehen, um mehr nicht.

Nein. Es geht darum, den Code ausdrücken zu lassen, was er bedeutet. Und 
da ist es eben unsinnig, 8-Bits eines Ports zu einer Ganzzahl zusammen 
zu fassen. Es sind einfach nur 8 (zusammenhanglose) Bits.

> Also warum der ganze Stress?

Welcher Stress?

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Markus F. schrieb:
> C hat Bitfelder.
>
> Ja, die sind implementation defined.

Ja!
Ich spreche aber gar nicht von Bitfeldern.

Autor: Markus F. (mfro)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Ich spreche aber gar nicht von Bitfeldern.

aber ich tu' das ;).

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Karl M. schrieb:
>> Hallo Wilhelm M. schrieb:
>>> Warum benötige ich zur Manipulation einzelner Bits einen Datentyp
>>> uint8_t, der ja vorzeichenlose Ganzzahlen repräsentieren soll?
>>
>> Die Frage ist doch schnell beantwortet, da ein Port eines AVR µC 8 Bit
>> Breit ist.
>
> 8-Bit als ein Byte zusammengefasst: ja.
>
> Aber diese 8-Bit immer als Ganzzahl interpretieren: klares nein.

Tut man ja auch weder bei dem &, noch bei dem <<. Man shiftet ja Bits 
und nicht eine Ganzzahl. Man interpretiert sie in dem Fall lediglich als 
einen zusammengehörigen Block aus 8 Bits, aber nicht als Ganzzahl.

: Bearbeitet durch User
Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Wilhelm M. schrieb:
>> Karl M. schrieb:
>>> Hallo Wilhelm M. schrieb:
>>>> Warum benötige ich zur Manipulation einzelner Bits einen Datentyp
>>>> uint8_t, der ja vorzeichenlose Ganzzahlen repräsentieren soll?
>>>
>>> Die Frage ist doch schnell beantwortet, da ein Port eines AVR µC 8 Bit
>>> Breit ist.
>>
>> 8-Bit als ein Byte zusammengefasst: ja.
>>
>> Aber diese 8-Bit immer als Ganzzahl interpretieren: klares nein.
>
> Tut man ja auch weder bei dem &, noch bei dem <<. Man shiftet ja Bits
> und nicht eine Ganzzahl. Man interpretiert sie in dem Fall lediglich als
> einen zusammengehörigen Block aus 8 Bits, aber nicht als Ganzzahl.

Dann lies mal genauer:

http://en.cppreference.com/w/c/language/operator_arithmetic

Autor: M. K. (sylaina)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> M. K. schrieb:
>> Dass du das "^" vergessen hast vor dem "=" ;)
>
> Nein, hat er nicht. Bei halbwegs aktuellen AVRs kann man ein Bit in
> einem PORT-Register toggeln, indem man eine 1 in das entsprechende Bit
> des dazugehörigen PIN-Registers schreibt.

Achja, stimmt ja. Da war ja noch was mit PINx...wo ist mein Kaffee?

Beitrag #5443421 wurde von einem Moderator gelöscht.
Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Ja, das mache ich auch schon sehr lange so ...
Zeigen!
(bitte)

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arduino F. schrieb:
> Wilhelm M. schrieb:
>> Ja, das mache ich auch schon sehr lange so ...
> Zeigen!
> (bitte)

Grundsätzlich: primitive Datentypen sind die kleinsten "Bausteine". 
Allerdings, sind sie in vielen Einsatzbereichen sowohl im Wertebereich 
wie auch in der Operationenmenge unpassend. Zudem tragen sie keinerlei 
Semantik. Das ist der Tatsache geschuldet, das wir es mit einer 
general-purpose Sprache zu tun haben (irgendetwas muss die Sprache ja 
bereitstellen). Für seine eigene, projektspezifische Problemdomäne 
sollte man sich eigene Datentypen maßgeschneidert erstellen.

Nun, es geht darum, einen Typ zu erstellen, der ein Byte, d.h. eine 
geordnete Sammlung von 8-Bits darstellt. Da diese 8-Bits zunächst keine 
Semantik haben, macht es keinen Sinn

i) implizite Typkonversionen von/zu arithmetischen DT zu erlauben
ii) arithmetische Rechenoperationen

zuzulassen. Als erlaubte Operationen kommt zunächst mal nur die 
Kopierzuweisung und die Kopierkonstruktion in Betracht.

Also
auto x = Byte{42};
auto y = x;
y = x;
soll möglich sein, aber
auto z1 = 2 * x;
auto z2 = x + y;
soll nicht möglich sein.

Die erste Möglichkeit, wäre ein Typ
struct Byte {
       uint8_t value;
};
zu schreiben. Eine andere Möglichkeit ist:
enum class byte : uint8_t {};

Ich habe die zweite Variante genommen, denn es gab mal einen 
gcc-Optimizer isra-Bug, der mit der ersten manchmal Schwierigkeiten 
hatte. Die scoped-enum Variante benutzt auch libstdc++.

Jetzt kann man anfangen, seine gewünschten Operation hinzuzufügen, etwa:
template<typename IType>
constexpr byte operator<<(byte b, IType shift) noexcept {
   return byte(static_cast<uint8_t>(b) << shift);
}
oder
constexpr bool any(std::byte b) noexecpt {
     return b != std::byte{0};
}
und andere.
Wobei man die Operatoren dann besser als SFINAE-enabled templates 
schreibt, falls man auch noch andere Bit-Typen hat, wie etwa Nibble, 
o.ä.


*Achtung*: an dieser Stelle kommt regelmäßig der Einwand:
Was, sooo viel Aufwand. Das mache ich doch mit C und int einfacher.

Dazu ist natürlich zu bedenken:

a) den Aufwand macht man sich für seine N-Projekte genau einmal.
b) für den Klienten ist es eben nicht aufwändiger
c) ich gewinne Sicherheit im Sinne von "ease to use, hard to misuse"
d) der Code wird expressiver

Das war es in Kürze und nur ganz grob.

: Bearbeitet durch User
Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven A. schrieb:
> was spricht denn dagegen? das steht sogar im datenblatt der controller,
> bei denen es möglich ist, das man so den pin toggled.

Dagegen spricht, daß jeder erstmal grübelt, wenn er nicht das Datenblatt 
im Kopf hat. Ich benutze es daher absichtlich nicht. In der Regel ist 
der Einspareffekt unerheblich.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:
> Sven A. schrieb:
>> was spricht denn dagegen? das steht sogar im datenblatt der controller,
>> bei denen es möglich ist, das man so den pin toggled.
>
> Dagegen spricht, daß jeder erstmal grübelt, wenn er nicht das Datenblatt
> im Kopf hat. Ich benutze es daher absichtlich nicht. In der Regel ist
> der Einspareffekt unerheblich.

Schaltest Du dann bei einem unechtem RMW auch die Interrupts aus und 
legst die anderen Kerne still?

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
>> Tut man ja auch weder bei dem &, noch bei dem <<. Man shiftet ja Bits
>> und nicht eine Ganzzahl. Man interpretiert sie in dem Fall lediglich als
>> einen zusammengehörigen Block aus 8 Bits, aber nicht als Ganzzahl.
>
> Dann lies mal genauer:
>
> http://en.cppreference.com/w/c/language/operator_arithmetic

Und dann?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.