Präprozessor - Exponnent

OP #3275470
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
#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.
Gast
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);
  }
Gast
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...
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

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.