Was macht das?
-
Hi,
#define memcpy(d,s,sz) \ do { \ for (int i=0;i<sz;i++) { \ ((char*)d)[i]=((char*)s)[i]; \ } \ ((char*)s)[ rand() % sz ] ^= 0xff; } \ while (0)
Aus https://gist.github.com/aras-p/6224951
Was aber genau macht die genannte Zeile?Danke
edit: umgebrochen
-
Das ist eine Spaß-Sammlung von Präprozessormakros, die für WIRKLICH scher zu findenden Fehler sorgt.
Zum Beispiel#define if(x) if ((x) && (rand() < RAND_MAX * 0.99))
bewirkt, daß ein if, das in den true-Zweig gehen müßte, in 1 Prozent der Fälle leider falsch abbiegt. Denke, beim Debiggen von sowas wird man wahnsinnig.
Dein memcpy-Makro macht das ganz normale memcpy und schreibt dann für den riesigen Fun in die Quelle ein Zufallsbyte. Das do … while(0) sorgt nur dafür, daß es sich in if oder schleifen wie ein einiger Funktionsaufruf anfühlt.
-
Zu beachten ist dass viele dieser Makros eigentlich ill-formed sind, da Schlüsselwörter keine Makronamen sein dürfen ([macro.names]/2).
in 1 Prozent der Fälle leider falsch abbiegt.
Glaube allerdings nicht dass es genau ein Prozent ist. Man müsste da mal die C++11 PRNG facility mit einbeziehen
@volkard: Haste eigentlich mal deine PNs gelesen?
-
Arcoth schrieb:
@volkard: Haste eigentlich mal deine PNs gelesen?
Jup. Hab leider mit anderen Sachen die Zeit voll.
-
volkard schrieb:
Arcoth schrieb:
@volkard: Haste eigentlich mal deine PNs gelesen?
Jup. Hab leider mit anderen Sachen die Zeit voll.
Ah, ok.
-
Arcoth schrieb:
Glaube allerdings nicht dass es genau ein Prozent ist. Man müsste da mal die C++11 PRNG facility mit einbeziehen
rand() ist hier gut genug. Was glaub Ihr, welche unglaublichen Schieflagen rand() haben sollte?
#include <iostream> #include <iomanip> #include <cstdlib> using namespace std; #define if(x) if ((x) && (rand() < RAND_MAX * 0.99)) int main() { double t=0; double s=0; for(;;){ int c=0; for(int i=0;i<10000000;++i){ if(1+1==2){ ++c; } } t+=10000000; s+=c; cout<<s<<' '<<t<<' '<<setprecision(9)<<s/t<<'\n'; } }
Was kommt raus?
1.97999986e+10 2e+10 0.989999931Es wäre wichtiger, mich auf meine Tippfehler aufmerksam zu machen.
-
rand() ist hier gut genug. Was glaub Ihr, welche unglaublichen Schieflagen rand() haben sollte?
rand
unterstelle ich gar nichts. Es ist nur so:0.99*RAND_MAX
ist (aufgerundet) nie genau 99% vonRAND_MAX
, selbst wennrand
perfekt gleichmäßig verteilt ist ist es nicht superpräzise. Dass es hier reicht ist offensichtlich. Und dass das alles eher scherzhaft gemeint war hoffentlich auch.Was deine Tippfehler anbelangt: Dafür kann man dich wirklich nicht verurteilen. Schließlich hat samsung die beste tstatur nur du hst sie nicht die spalten zwischen den tasten sind groß und die tsten flach einfach genial
-
#include <iostream> #include <iomanip> #include <random> using namespace std; int main() { minstd_rand mt(random_device{}()); uniform_int_distribution<std::uint_fast32_t> uni(0, 99); double t=0; double s=0; for(;;) { int c=0; for(int i=0;i<10000000;++i) c += !!uni(mt); t+=10000000; s+=c; cout<<s<<' '<<t<<' '<<setprecision(9)<<s/t<<'\n'; } }
Gibt mir
7.64279996e+09 7.72e+09 0.989999995 [...] 9.49409996e+09 9.59e+09 0.989999996 9.50399994e+09 9.6e+09 0.989999994 [...] 9.89999976e+09 1e+10 0.989999976 9.90989996e+09 1.001e+10 0.989999996
das ist imo präziser, über die Signifikanz kann man streiten.
-
volkard schrieb:
Das ist eine Spaß-Sammlung von Präprozessormakros, die für WIRKLICH scher zu findenden Fehler sorgt.
Zum Beispiel#define if(x) if ((x) && (rand() < RAND_MAX * 0.99))
bewirkt, daß ein if, das in den true-Zweig gehen müßte, in 1 Prozent der Fälle leider falsch abbiegt. Denke, beim Debiggen von sowas wird man wahnsinnig.
Dein memcpy-Makro macht das ganz normale memcpy und schreibt dann für den riesigen Fun in die Quelle ein Zufallsbyte. Das do … while(0) sorgt nur dafür, daß es sich in if oder schleifen wie ein einiger Funktionsaufruf anfühlt.
Was die Sammlung ist, ist mir schon klar - nur die eine Zeile ist mir etwas unklar
Nochmal zu dem memcpy: nachdem ich mit memcpy eigentlich nie was zu tun hatte - was hat das für Folgen? Und was heißt "Funktionsauruf anfühlt"?
Was mich sehr an der Zeile verwirrt ist
((char*)s)[ rand() % sz ] ^= 0xff;
^= ist doch XOR? Was macht die Zeile dann aber?
-
Ich vermisse
#define free(x) (rand() % 2 ? free(x) : (void)0)
^= ist doch XOR? Was macht die Zeile dann aber?
xor 0xFF flippt alle bits.
-
Steps schrieb:
Was die Sammlung ist, ist mir schon klar
Ich weiß. Ich habs nur dazugeschrieben für die anderen Leser, damit sie wissen, ob sie Lust haben, Deinen Link zu verfolgen.
-
Steps schrieb:
volkard schrieb:
Das do … while(0) sorgt nur dafür, daß es sich in if oder schleifen wie ein einiger Funktionsaufruf anfühlt.
Und was heißt "Funktionsauruf anfühlt"?
Ich machs an einer fehlerhaften Implementierung deutlich:
#define memcpy(d,s,sz) \ { \ for (int i=0;i<sz;i++) { \ ((char*)d)[i]=((char*)s)[i]; \ } \ ((char*)s)[ rand() % sz ] ^= 0xff; \ }
und dann benutzt man es
if(…) memcpy(…);
ok.
aber
if(…) memcpy(…)
geht auch, das ist ja komisch.
und
if(…) memcpy(…) else foo();
geht.
und
undif(…) memcpy(…); else foo();
geht NICHT!
So ein {} im Makro muss also irgendwie ein Folgendes Semikolon an sich binden.
if(true){//hier warnt gcc rum … } else//hier könnte man vors semikolon noch was schreiben
oder
do{ … }while(0)//keine warnung, weil die gcc-leute diesen trick selber nutzen
oder dank C++11
[](){ … }()