c prog, usefull macros, u32->f, f->u32, better do/while block

OP (Firma: @home) #6160377
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
#6160405
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?
OP (Firma: @home) #6160563
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
#6160987
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;
#6161060
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.
OP (Firma: @home) #6161066
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
Gast #6161150
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
OP (Firma: @home) #6161186
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))
Angehängte Dateien:
Gast #6161207
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.
OP (Firma: @home) #6161256
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
OP (Firma: @home) #6161275
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren