Forum: Mikrocontroller und Digitale Elektronik c prog, usefull macros, u32->f, f->u32, better do/while block


von Apollo M. (Firma: @home) (majortom)


Lesenswert?

hi, aus meiner schatzkiste ...
wird bei mir verwendet in meiner eeprom wear-leaving lib um mit einer 
function im eeprom uint32_t und float read/write zu realisieren!
braucht c99 support

1
#define CONV_U32(x) ((const union {float f; uint32_t u;}) {.f = (x)}.u)
2
#define CONV_FLOAT(x) ((const union {float f; uint32_t u;}) {.u = (x)}.f)

one more, replacement of do{...}while(0), weil do/while hat ein PROBLEM 
mit ablauf control statements im block, e.g. bei break und die version 
hier nicht!

1
#define MACRO_BLOCK(...) if(1) {__VA_ARGS__} else((void)0)

irgendwann mal ausgegraben bzw. inspiriert von 
https://gustedt.wordpress.com


mt

von Bauform B. (bauformb)


Lesenswert?

Apollo M. schrieb:
> lib um mit einer function im eeprom uint32_t und float read/write
> zu realisieren!
1
#define CONV_U32(x) ((const union {float f; uint32_t u;}) {.f = (x)}.u)
2
#define CONV_FLOAT(x) ((const union {float f; uint32_t u;}) {.u = (x)}.f)
Gibt es eigentlich eine "offizielle" Möglichkeit, float ins EEPROM zu 
bringen? Eine temporäre Kopie mit memcpy() in ein uint8_t Array? Oder 
eeprom_write (void *value, size_t size)?

> one more, replacement of do{...}while(0), weil do/while hat ein PROBLEM
> mit ablauf control statements im block, e.g. bei break

Naja, vielleicht sollte man seltsame Konstruktionen wie do{...}while(0) 
garnicht erst verwenden, dann müsste man sie nicht durch noch schlechter 
lesbare ersetzen?

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Bauform B. schrieb:
> Gibt es eigentlich eine "offizielle" Möglichkeit,

ja,
eeprom_read/write/update_byte/word/dword/float/block(...)

schau vielleicht auch mal in avr/eeprom.h nach!
ich benutzte dank dem macro nur die dword variante.


Bauform B. schrieb:
> Naja, vielleicht sollte man seltsame Konstruktionen wie do{...}while(0)
> garnicht erst verwenden

nix seltsam, block instruction macros sind sehr nützlich, aber sicher 
nichts für macro hasser oder newbies.


mt

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

... next und immer wieder gern gesehen!
1
#define sizeofmem(t,m) sizeof(((t*)0)->m) // size of struct member
2
#define sizeoflen(a) (sizeof(a)/sizeof(a[0])) // size of array element

von Dirk K. (merciless)


Lesenswert?

Warum benutzt man sowas?
1
do { 
2
  // some code
3
} while(0);

merciless

von Jim M. (turboj)


Lesenswert?

Dirk K. schrieb:
> Warum benutzt man sowas?

Als GOTO Ersatz:
1
do {
2
3
  if (a) { foo(); break; }
4
  if (b) { bar(); break;}
5
  baz();
6
7
8
} while(0);

In Makros auch gerne mal ohne das abschließende Semikolon:
1
#define doFoo do { foo1(); foo2();} while (0)


Hintergrund ist dabei u.a. das halbwegs korrekte Verhalten im if
1
  if (1) doFoo; else doBar;

von Bauform B. (bauformb)


Lesenswert?

Jim M. schrieb:
> Dirk K. schrieb:
>> Warum benutzt man sowas?
>
> Als GOTO Ersatz:
> do {
>
>   if (a) { foo(); break; }
>   if (b) { bar(); break;}
>   baz();
>
> } while(0);

Ja, ok, aber warum tut man sich und anderen sowas an? Oder ist das der 
erste Versuch für den Obfuscated C Code Contest? Wenn es als 
schlechtes Beispiel dienen soll, sollte man das aber deutlicher dazu 
schreiben.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Dirk K. schrieb:
> Warum benutzt man sowas?

wenn du ein macro haben willst , das mehrere beliebige anweisungen 
beinhaltet würde dieses unerwünschte seiteneffekte haben in if/else, 
for/while ...
mit der "umrahmung" do/while(0) oder besser if(1)/else wird aus dieser 
sequenz von anweisungen ein block, der diese seiteneffekte verhindert.

while/do hat aber e.g. das problem, wenn in dem block eine for schleife 
mit einer break condition steht, dass dieses break zum do/while rahmen 
zugeordnet wird und nicht wie beabsichtigt zur for schleife.


Jim M. schrieb:
> Als GOTO Ersatz:

verstehe/kenne ich nicht?!


mt

von Cyblord -. (cyblord)


Lesenswert?

Solche Makro-Monster führen direkt in die Hölle.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Cyblord -. schrieb:
> Solche Makro-Monster führen direkt in die Hölle.

weichei!

ich habe noch mehr zauberwaffen macros!
z.b. für non-blocking timed (periodic, x-times, single shot) instruction 
blocks

die conv macros finde ich sehr schlau!
sind aber auch nicht von  mir, bin da nur ein ideen-verwerter.


mt

von Bauform B. (bauformb)


Lesenswert?

Apollo M. schrieb:
> ich habe noch mehr zauberwaffen macros!
> die conv macros finde ich sehr schlau!

Ah, Weapons of Math Destruction :)

von DPA (Gast)


Lesenswert?

Ich habe auch noch ein paar praktische macros:
1
#define STR(A) STR_EVAL(A)
2
#define STR_EVAL(A) #A
3
4
#define UNPACK(...) __VA_ARGS__
5
6
#define CONCAT(A, B) CONCAT_EVAL(A, B)
7
#define CONCAT_EVAL(A, B) A ## B
8
9
#define container_of(ptr, type, member) \
10
  ((type*)( (ptr) ? (char*)(ptr) - offsetof(type, member) : 0 ))

Das UNPACK macro ist vor allem in macros interessant. Bei "#define 
X(A,B,C) UNPACK B" wird aus X(a,(b,c),d) dann b,c

von Apollo M. (Firma: @home) (majortom)


Angehängte Dateien:

Lesenswert?

DPA schrieb:
> #define UNPACK(...) __VA_ARGS__

äh, hier fehlt doch was?

die concat und str macros sind basic, container_of sieht interessant 
aus!

mein link oben führt zur p99 macro library, da gibt es irre macros. da 
verstehe ich bis jetzt nur bahnhof. sogar rekursion, unroll functions 
habe ich dort gesehen.

just hardcore and magic!

hier mal noch ein leckerli ... für arduino jünger und andere

//macros for a non blocking wait, periodic or x-times repeated 
intruction block!
//needs millis() or micros() system function
//should be located inside a fast loop

//usage:
// PERIODIC(MSEC,T2B,500) {digitalWrite(LED_PIN, 
digitalRead(LED_PIN)^1); //...} //blinky led
1
//options
2
#define USEC micros() //timer tick base
3
#define MSEC millis()
4
#define T2B uint16_t  //timer data type
5
#define T4B uint32_t
6
7
//create an unique name from given parameter and line number
8
#define UNIQUE(name) (name ## __LINE__)
9
10
//creates an unique timer for each instance
11
#define PERIODIC(tb, dt, t) \
12
  static dt UNIQUE(tmr) = (dt) tb; \
13
  if ((tb - UNIQUE(tmr) >= t) \
14
  && (UNIQUE(tmr) = tb, 1)) //(UNIQUE(tmr) += t, 1))

von Nop (Gast)


Lesenswert?

Apollo M. schrieb:

> while/do hat aber e.g. das problem, wenn in dem block eine for schleife
> mit einer break condition steht, dass dieses break zum do/while rahmen
> zugeordnet wird und nicht wie beabsichtigt zur for schleife.

Äh, nein, umgedreht. Das break bezieht sich auf die innerste Schleife, 
also hier wie beabsichtigt auf die for-Schleife.

Das Problem ist vielmehr, daß man im Block kein break verwenden kann, 
das sich auf ein Konstrukt außerhalb des Makros bezieht, eben weil es 
auf die while-Schleife bezogen wird.

Andererseits sollte man das ohnehin nicht tun, weil das Macro dann 
starke Annahmen über die Umgebung machen muß, in der es aufgerufen wird.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Nop schrieb:
> Äh, nein, umgedreht. Das break bezieht sich auf die innerste Schleife,
> also hier wie beabsichtigt auf die for-Schleife.

ich versteh das anders, lese mal hier ...
https://gustedt.wordpress.com/2011/02/02/handling-control-flow-inside-macros/

von Nop (Gast)


Lesenswert?

Apollo M. schrieb:

> ich versteh das anders, lese mal hier ...

Da ist die for-Schleife aber nicht innerhalb des Macros, sondern ein 
Konstrukt außerhalb.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Nop schrieb:
> Da ist die for-Schleife aber nicht innerhalb des Macros, sondern ein
> Konstrukt außerhalb.

korrekt, dein hinweis!

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Nop schrieb:
> das Problem ist vielmehr, daß man im Block kein break verwenden kann,
> das sich auf ein Konstrukt außerhalb des Makros bezieht, eben weil es
> auf die while-Schleife bezogen wird.

danke, auch dieser hinweis passt!
ich habe jetzt jedenfalls do/while abgeschworen und nutze das if/else 
macro.
bin vorher auch garnicht auf die idee gekommen das als macro zu 
verpacken, sondern habe immer händisch do/while gecodet.


mt

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

hinweis, interessant ist, was in den timed_block macros in dem if 
statement alles so abgeht ... via co-logic/short cut/circuit logic

1. periodic tmr abgelaufen?
2. repeat cnt abgelaufen?
3. repeat cnt dec, periodic tmr restart, if(true)
1
if ((tb - UNIQUE(tmr) >= t) 
2
   && UNIQUE(xRepeats) 
3
   && (UNIQUE(xRepeats)--, UNIQUE(tmr) = tb, 1))
mt

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.