Forum: Compiler & IDEs Präprozessor - Exponnent


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,
kennt jemand eine Möglichkeit, den Präprozessor konstante Potenzen 
berechnen zu lassen? Konkret suche ich etwas wie:
1
#define N_DIGITS 3
2
3
void fcn(uint16_t a) {
4
  a %= pow(10,NDIGITS);
5
  ...
6
}
um den konstanten Term auf der rechten Seite schon im Präprozessor 
ausrechnen zu können. Wenn ich das richtig sehe, gibt es ja keinen 
Exponnentialoperator und keine Schleifen.

Viele Grüße
Nicolas

von (prx) A. K. (prx)


Lesenswert?

Der Präprozessor rechnet nicht. Ausnahme: der Operand in #if.

von Walter T. (nicolas)


Lesenswert?

A. K. schrieb:
> Der Präprozessor rechnet nicht. Ausnahme: der Operand in #if.

OK, laß es mich präzisieren: Mit Präprozessormagie dafür sorgen, daß der 
GCC Konstanten daraus macht. OK, ich könnte es für sinnvolle Werte 
einfach mit einer switch-case-Tabelle machen. Aber ist das schön?

von (prx) A. K. (prx)


Lesenswert?

#define N 3
#define CAT(a,b) a##b
#define CAT2(a,b) CAT(a,b)

CAT2(10e,N) => 10e3

Ist es das, was du willst?

Anonsten werden Compiler u.U. konstante Ausdrücke bereits selbst 
berechnen. Nicht selten sogar dann, wenn bekannte Mathefunktionen wie 
exp() dazu gehören.

von Walter T. (nicolas)


Lesenswert?

Ich will zwar 1e3 (SCNR), aber ja, genau das ist es, was ich suche. 
Vielen Dank!

von Dave (Gast)


Lesenswert?

Modern ist aber eher constexpr.

Ok, das ist c++. Wenn man richtig damit umgeht, ist das für einen uC 
aber auch bestens geeignet.

von chris (Gast)


Lesenswert?

Ansonsten wird of so ein workaround gemacht:

#define N_DIGITS 3
#define pow_1(x) (x)
#define pow_2(x) pow_1(x*x)
#define pow_3(x) pow_1(x*x*x)
#define pow_4(x) pow_1(x*x*x*x)
#define pow_5(x) pow_1(x*x*x*x*x)
#define pow_6(x) pow_1(x*x*x*x*x*x)
#define pow_7(x) pow_1(x*x*x*x*x*x)
#define pow_8(x) pow_1(x*x*x*x*x*x)

#define pp_pow__(x,y) pow_##y(x)
#define pp_pow_(x,y) pp_pow__((x),y))
#define pp_pow(x,y) pp_pow_((x),y))

void fcn(uint16_t a) {
  a %= pp_pow(10,N_DIGITS);
  }

von Dr. Sommer (Gast)


Lesenswert?

1
#include <iostream>
2
 
3
template <typename T>
4
constexpr const T clPow (const T& base, const unsigned int exp) {
5
    return exp == 0 ? T{1} : clPow<T> (base, exp-1) * base;
6
}
7
 
8
int main () {
9
    constexpr int x = clPow (10, 4);
10
    std::cout << x << std::endl;
11
}
"constexpr" zwingt den Compiler die Werte beim Compilieren auszurechnen. 
Funktioniert außerdem auch zur Laufzeit. So vermeidet man den 
Präprozessor komplett mit allen seinen Fallen & Nachteilen...

von Walter T. (nicolas)


Lesenswert?

Woher kommt eigentlich dieses Konstrukt:
1
#define CAT(a,b) a##b
2
#define CAT2(a,b) CAT(a,b)

Ich habe es schon in vielen Quelltexten gesehen?

von (prx) A. K. (prx)


Lesenswert?

## verkettet die Parameter ohne Leerzeichen zwischendrin.

Eine zweistufige Staffelung der CAT Makros ist erforderlich, weil sonst 
Makros als Parameter nicht aufgelöst werden. CAT(10e,N) führt zu 10eN.

von Andreas B. (andreas_b77)


Lesenswert?

test.c:
1
#include <math.h>
2
3
double test(void)
4
{
5
  return pow(10, 3);
6
}
7
8
int testi(void)
9
{
10
  return pow(10, 3);
11
}

Compile:
1
avr-gcc -c -Os test.c

Ergebnis:
1
test.o:     file format elf32-avr
2
3
4
Disassembly of section .text:
5
6
00000000 <test>:
7
   0:  60 e0         ldi  r22, 0x00  ; 0
8
   2:  70 e0         ldi  r23, 0x00  ; 0
9
   4:  8a e7         ldi  r24, 0x7A  ; 122
10
   6:  94 e4         ldi  r25, 0x44  ; 68
11
   8:  08 95         ret
12
13
0000000a <testi>:
14
   a:  88 ee         ldi  r24, 0xE8  ; 232
15
   c:  93 e0         ldi  r25, 0x03  ; 3
16
   e:  08 95         ret

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.