C - Function / Define / Macro / Obfuscated C ?

OP (Firma: IGL) #5712630
Lesenswert?

Hallo zusammen,

in einem mpeg-Decoder fand ich folgende Macro Funktion:
1
#include <stdint.h>
2

3
#ifndef cmuls
4
#define cmuls(dre, dim, are, aim, bre, bim) \
5
do { \
6
  int32_t tre; \
7
  (tre) = (int32_t)(((int64_t)(are)* (int64_t)(bre)-(int64_t)(aim)* (int64_t)(bim)) >> 31); \
8
  (dim) = (int32_t)(((int64_t)(are)* (int64_t)(bim)+(int64_t)(aim)* (int64_t)(bre)) >> 31); \
9
  (dre) = tre; \
10
} while (0)
11
#endif

Ich habe daraus folgendes Test-Programm gemacht:
1
#include <stdint.h>
2

3
#ifndef cmuls
4
#define cmuls(dre, dim, are, aim, bre, bim) \
5
do { \
6
  int32_t tre; \
7
  (tre) = (int32_t)(((int64_t)(are)* (int64_t)(bre)-(int64_t)(aim)* (int64_t)(bim)) >> 31); \
8
  (dim) = (int32_t)(((int64_t)(are)* (int64_t)(bim)+(int64_t)(aim)* (int64_t)(bre)) >> 31); \
9
  (dre) = tre; \
10
} while (0)
11
#endif
12

13
#ifndef Test1
14
#define Test1(dre) \
15
do { \
16
  (dre) = (dre)+1; \
17
} while (0)
18
#endif
19

20
int main()
21
{
22
  int32_t aa, a, b, c, d, e, f;
23
  a = 0x1C954; //117076;
24
  b = 0x520C;  //21004;
25
  c = 0x1C954; // 117076;
26
  d = 0x520C;  //21004;
27
  e = 0x6DC25403; // 1841452035;
28
  f = 0xBE2500CB; // 3190096075;    
29
  cmuls(a,b,c,d,e,f);
30

31
  aa = 0;
32
  Test1(aa); 
33
  int32_t ergebnis = aa; // Ergebnis 1
34
  return 0;
35
}

Ich sehe bei der Art eine Funktion zu definieren nur Nachteile außer 
dass sie vielleicht einen Bruchteil einer Sekunde schneller ist!!!


Jetzt meine Frage:

Gibt es irgendeineinen Grund eine Funktion so zu definieren ?
OP (Firma: IGL) #5712698
Lesenswert?

Timmo H. schrieb:
> Andreas V. schrieb:
>> A. K. schrieb:
>> Inline-Funktionen sind eleganter.
>>
>> Inline ist doch ein C++ Keyword oder?
> Nö

Sorry mein C ist ein bissl eingerostet. Liegt am Compiler bzw. an den 
Einstellungen. Ich kriege es jedenfalls nur als C++ compiliert...

Ich frage mich halt nur warum man solche "#define" Definitionen für 
Funktionen wie oben heute noch macht. Mal abgesehen davon dass der 
Debugger streikt.
Gast #5712814
Lesenswert?

Wie alt ist eigentlich die Library? Und wie alt ist der Programmierer?

Erster Verdacht ist doch - das stammt aus einer Zeit, als wir uns noch 
nicht auf die Optimierung von Funktionsaufrufen verlassen konnten.
#5712825
Lesenswert?

Archeologe schrieb:
> Erster Verdacht ist doch - das stammt aus einer Zeit, als wir uns noch
> nicht auf die Optimierung von Funktionsaufrufen verlassen konnten.

Oder - wie oben schon erwähnt wurde - es soll auch auf Compilern, die 
aus dieser Zeit stammen, zu effizientem Code führen.

Andreas V. schrieb:
> Ich sehe bei der Art eine Funktion zu definieren nur Nachteile außer
> dass sie vielleicht einen Bruchteil einer Sekunde schneller ist!!!

Naja, wie oft wird sie denn aufgerufen? Wenn das z.B. im Dekoder für 
jeden Pixel mehrmals aufgerufen wird, ist das bei einem 4k-Video mit 
60fps schon verdammt viel. Da lohnt es sich ggf. auch,

> einen Bruchteil einer Sekunde

bei jedem Aufruf zu sparen!!!1einself-Ausrufezeichen
Gast #5712863
Lesenswert?

Andreas V. schrieb:
> Die Frage wäre dann: Spart man mit einem modernen Compiler
> wirklich
> Zeit?

Bei #define: nie - sind ja nur Textersetzungen. Diese koennen zur 
besseren Lesbarkeit von Code beitragen.

Bei Assembler-Code in GCC habe ich vor ca. 15 Jahren aufgegeben 
haendisch einzugreifen (Tailcode-Opt., Loop-Unrolling, FP-Code, ...) 
kann der GCC inzwischen besser.
Bei anderen C-Compilern wird das ca. gleich sein.

leo
#5712864
Lesenswert?

Andreas V. schrieb:
> Inline ist doch ein C++ Keyword oder?

Nein.

Walter T. schrieb:
> Wenn alle Aufruf-Parameter zur Compilezeit konstant ist, wird aus dem
> Makro eine Konstante.

Mit ganz, ganz viel Glück könnte dir der Compiler eine Funktion auch so 
optimieren.
In C++ gibts constexpr dafür.

Andreas V. schrieb:
> Die Frage wäre dann: Spart man mit einem modernen Compiler wirklich
> Zeit?

Eher nein, wobei es natürlich auch schrottige Compiler gibt.
#5712876
Lesenswert?

vn n. schrieb:
> Andreas V. schrieb:
>> Inline ist doch ein C++ Keyword oder?
>
> Nein.

Um das etwas genauer zu erläutern: Es gibt in beiden Sprachen ein 
Schlüsselwort "inline", allerdings nicht ganz in der selben Bedeutung.

> Walter T. schrieb:
>> Wenn alle Aufruf-Parameter zur Compilezeit konstant ist, wird aus dem
>> Makro eine Konstante.
>
> Mit ganz, ganz viel Glück könnte dir der Compiler eine Funktion auch so
> optimieren.

So arg viel Glück braucht man nicht. Die Funktion muss nur inline sein, 
und sofern man keine LTO hat, muss sie an der Stelle des Aufrufs der 
Quellcode sichtbar sein. Und natürlich muss die Funktion auch dazu 
geeignet sein (also z.B. nicht rekursiv).

> In C++ gibts constexpr dafür.

Bei GCC kann man (sowohl in C, als auch in C++) ein Inlining erzwingen 
mit __attribute__((always_inline)).

> Andreas V. schrieb:
>> Die Frage wäre dann: Spart man mit einem modernen Compiler wirklich
>> Zeit?
>
> Eher nein, wobei es natürlich auch schrottige Compiler gibt.

Man braucht aber auch nicht mehr Zeit gegenüber einer Inline-Funktion.
#5712887
Lesenswert?

Rolf M. schrieb:
> So arg viel Glück braucht man nicht. Die Funktion muss nur inline sein,
> und sofern man keine LTO hat, muss sie an der Stelle des Aufrufs der
> Quellcode sichtbar sein. Und natürlich muss die Funktion auch dazu
> geeignet sein (also z.B. nicht rekursiv).

Grundsätzlich ja, aber da wär halt noch das Thema "Code für 
uralte/schrottige Compiler".
Aber ja, vielleicht ist auch einfach nur der Code schrottig. Wenn man 
schon sowas macht, um es z.B. auch exotischen Compilern recht zu machen, 
sollte man es zumindest in einem Kommentar vermerken.

Rolf M. schrieb:
> Man braucht aber auch nicht mehr Zeit gegenüber einer Inline-Funktion.

Korrekt.
Wobei inline ja "erst" (oh Gott wird man alt) mit C99 Standard wurde 
(vorher aber von diversen Compilern schon unterstützt wurde), womit wir 
wieder beim Thema uralte/schrottige Compiler wären.
#5712903
Lesenswert?

Per Makro kommt in besten Fall etwas Konstantes raus (z.B. x = 234). Mit 
Inline kann es auch dynamisch sein ( x = y*203). Wenn man mit -O2 (am 
schnellsten) kompiliert, dann werden Funktionen auch automatisch Inline 
kompiliert wenn es schneller ist. Aber ein Makro läuft durch den 
Präprozessor  und erzeugt dadurch im besten Fall etwas schnelleren Code 
wenn es sinnvoll eingesetzt wurde.
OP (Firma: IGL) #5712999
Lesenswert?

Ich habe noch mal die Varianten ausprobiert, weil ich mir nicht mehr 
sicher war wie sich das bei aktuellen Compilern verhält. Dazu schrieb 
ich folgenden Code (und ja es kommt immer das gleiche Ergebnis heraus):
1
#include<stdio.h>
2
#include<stdint.h>
3
#include<time.h> 
4
#include <windows.h>
5

6
#ifndef cmuls
7
#define cmuls(dre, dim, are, aim, bre, bim) \
8
do { \
9
  int32_t tre; \
10
  (tre) = (int32_t)(((int64_t)(are)* (int64_t)(bre)-(int64_t)(aim)* (int64_t)(bim)) >> 31); \
11
  (dim) = (int32_t)(((int64_t)(are)* (int64_t)(bim)+(int64_t)(aim)* (int64_t)(bre)) >> 31); \
12
  (dre) = tre; \
13
} while (0)
14
#endif
15

16
inline void cmuls2(int32_t* dre, int32_t* dim, int32_t* are, int32_t* aim, int32_t* bre, int32_t* bim)
17
{
18
  int32_t tre; 
19
  (tre) = (int32_t)(((int64_t)(*are)* (int64_t)(*bre)-(int64_t)(*aim)* (int64_t)(*bim)) >> 31); 
20
  (*dim) = (int32_t)(((int64_t)(*are)* (int64_t)(*bim)+(int64_t)(*aim)* (int64_t)(*bre)) >> 31); 
21
  (*dre) = tre; 
22
}
23

24
void cmuls3(int32_t* dre, int32_t* dim, int32_t* are, int32_t* aim, int32_t* bre, int32_t* bim)
25
{
26
  int32_t tre;
27
  (tre) = (int32_t)(((int64_t)(*are)* (int64_t)(*bre) - (int64_t)(*aim)* (int64_t)(*bim)) >> 31);
28
  (*dim) = (int32_t)(((int64_t)(*are)* (int64_t)(*bim) + (int64_t)(*aim)* (int64_t)(*bre)) >> 31);
29
  (*dre) = tre;
30
}
31

32

33

34
#ifndef Test1
35
#define Test1(dre) \
36
do { \
37
  (dre) = (dre)+1; \
38
} while (0)
39
#endif
40

41
inline int max2(int a, int b) 
42
{
43
  int z = a > b ? a : b;
44
  return z;
45
}
46

47
int main()
48
{  
49
  clock_t t1, t2;
50
  
51
  double diff1, diff2, diff3 = 0.0;
52
  int32_t a, b, c, d, e, f;
53
  a = 0x1C954; //117076;
54
  b = 0x520C;  //21004;
55
  c = 0x1C954; // 117076;
56
  d = 0x520C;  //21004;
57
  e = 0x6DC25403; // 1841452035;
58
  f = 0xBE2500CB; // 3190096075;    
59
  int maxCnt = 10000000;
60

61
  for (int nTests = 0; nTests < 100; nTests++)
62
  {
63
    a = 1;
64
    b = 2;
65
    c = 3;
66
    d = 4;
67
    e = 5;
68
    f = 6;
69
    t1 = clock();
70
    for (int x = 0; x < maxCnt; x++)
71
    {
72
      cmuls(a, b, c, d, e, f);
73
    }
74
    t2 = clock();
75
    diff1 = ((double)(t2 - t1) / CLOCKS_PER_SEC * 1000.0f);
76
    //printf("cmuls : %5u ms\n", (unsigned)diff1);
77
    //printf("%5u %5u %5u %5u %5u %5u\n", (unsigned)a, (unsigned)b, (unsigned)c, (unsigned)d, (unsigned)e, (unsigned)f);
78

79

80

81
    a = 1;
82
    b = 2;
83
    c = 3;
84
    d = 4;
85
    e = 5;
86
    f = 6;
87
    t1 = clock();
88
    for (int x = 0; x < maxCnt; x++)
89
    {
90
      cmuls2(&a, &b, &c, &d, &e, &f); // -1, 0, 3, 4, 5, 6    
91
    }
92
    t2 = clock();
93
    diff2 = ((double)(t2 - t1) / CLOCKS_PER_SEC * 1000.0f);
94
    //printf("cmuls2: %5u ms\n", (unsigned)diff2);
95
    //printf("%5u %5u %5u %5u %5u %5u\n", (unsigned)a, (unsigned)b, (unsigned)c, (unsigned)d, (unsigned)e, (unsigned)f);
96

97

98
    a = 1;
99
    b = 2;
100
    c = 3;
101
    d = 4;
102
    e = 5;
103
    f = 6;
104
    t1 = clock();
105
    for (int x = 0; x < maxCnt; x++)
106
    {
107
      cmuls3(&a, &b, &c, &d, &e, &f); // -1, 0, 3, 4, 5, 6
108
    }
109
    t2 = clock();
110
    diff3 = ((double)(t2 - t1) / CLOCKS_PER_SEC * 1000.0f);
111
    //printf("cmuls3: %5u ms\n", (unsigned)diff3);
112
    //printf("%5u %5u %5u %5u %5u %5u\n", (unsigned)a, (unsigned)b, (unsigned)c, (unsigned)d, (unsigned)e, (unsigned)f);
113

114
    double perc1 = diff1 / diff3 * 100.0;
115
    double perc2 = diff2 / diff3 * 100.0;
116
    double perc3 = 100.0f;
117

118
    printf("cmuls1: %03.2f \t", perc1);
119
    printf("cmuls2: %03.2f \t", perc2);
120
    printf("cmuls3: %03.2f \n", perc3);
121

122
    printf("");
123
  }
124

125
      return 0;
126
}

Ohne dass ich jetzt groß mit Compileroptionen herumspiele bekomme ich 
bei 100 Durchläufen mit jeweils 10 Mio. Berechnungen folgende 
Durchschnittswerte heraus:

 67,78% (Macro-Variante)

 67,01% (Inline-Variante)

100,00% (Nicht optimierter Code, immer langsamer)


Wobei die Prozentzahl die Ausführzeit im Verhältnis zum nicht 
optimierten Code angibt.
Gast #5713903
Lesenswert?

Andreas V. schrieb:
> 67,78% (Macro-Variante)
>
>  67,01% (Inline-Variante)
>
> 100,00% (Nicht optimierter Code, immer langsamer)
>
> Wobei die Prozentzahl die Ausführzeit im Verhältnis zum nicht
> optimierten Code angibt.

Ich frage mich, wieso dein Compiler die Rechnungen überhaupt zur 
Laufzeit ausführen lässt. Mein GCC und Clang schmeißen die Rechnungen ab 
-O2 einfach komplett raus.
#5713938
Lesenswert?

Jemand schrieb:
> Andreas V. schrieb:
>> 67,78% (Macro-Variante)
>>
>>  67,01% (Inline-Variante)
>>
>> 100,00% (Nicht optimierter Code, immer langsamer)
>>
>> Wobei die Prozentzahl die Ausführzeit im Verhältnis zum nicht
>> optimierten Code angibt.
>
> Ich frage mich, wieso dein Compiler die Rechnungen überhaupt zur
> Laufzeit ausführen lässt. Mein GCC und Clang schmeißen die Rechnungen ab
> -O2 einfach komplett raus.

Vermutlich passierte das bei obiger Messung in jedem Fall. 10^7 
Schleifendurchläufe dürften wohl nur dann fast genau so schnell sein wie 
(k)einer, wenn sie nicht passieren. Es ist eher so, daß -O0 50% länger 
für das Zeitmessen braucht. Statt der Messung würde ich erst mal
asm volatile "nop"
um die Schleifen packen und mir den generierten Code anschauen. Mehr als 
die Zuweisung von Konstanten an a und b wird da nicht stehen, wenn 
überhaupt.
Eher:
1
     NOP
2
     NOP
OP (Firma: IGL) #5713942
Lesenswert?

Ich hätte auch den "Time"-Befehl verwenden können, aber dazu hätte ich 
den Test anders aufbauen müssen!...

Die Rechnungen wurden ausgeführt. Man könnte den Durchlauf einer 
Leerschleife abziehen, aber mir ging es hierbei nur darum eine 
Hausnummer zu bekommen was schneller ist....
Gast #5713981
Lesenswert?

Andreas V. schrieb:
> Die Rechnungen wurden ausgeführt.

Aber warum?

> mir ging es hierbei nur darum eine
> Hausnummer zu bekommen was schneller ist....

Welchen Compiler verwendest du überhaupt? Eine derart schlechte 
Verbesserung auf nur 67 % im Vergleich zum unoptimierten Maschinencode 
bekomme ich hier mit deinem Quellcode nicht nachgestellt. (oder der 
unoptimierte Maschinencode ist einfach krass gut)
OP (Firma: IGL) #5714072
Lesenswert?

Jemand schrieb:
> Welchen Compiler verwendest du überhaupt? Eine derart schlechte
> Verbesserung auf nur 67 % im Vergleich zum unoptimierten Maschinencode
> bekomme ich hier mit deinem Quellcode nicht nachgestellt. (oder der
> unoptimierte Maschinencode ist einfach krass gut)

In dem Fall nahm ich den:
   VC C/C++ Optimizing Compiler Version 18.00.21005.1 for x86

Ich kann es aber auch mal mit dem IAR für MSP mal ausprobieren:
   IAR 6.40.1
OP (Firma: IGL) #5714168
Lesenswert?

Also beim IAR:
1
5 Messungen:
2
(Macro-Variante)  (Inline-Variante)  (nicht optimiert)  
3
68,8                   74,9             100
4
74,0                   71,8             100
5
98,6                   100              100
6
100,3                  97,85            100
7
106,9                  101,6            100
8

9

10
5 Messungen:
11
IAR mit Schalteroption Opimization High / Speed
12
(Macro-Variante)  (Inline-Variante)  (nicht optimiert)
13
98,2                  100,6             100
14
100,1                  97               100
15
99,8                   98,7             100
16
100,5                  99,6             100
17
105,7                  98,9             100
OP (Firma: IGL) #5714218
Lesenswert?

mh schrieb:
> Andreas V. schrieb:
>> (Macro-Variante)  (Inline-Variante)  (nicht optimiert)
>
> Mit "nicht optimiert" meinst du die cmuls3 Funktion und nicht -O0?

Ja. Ich meinte die Funktion cmuls3!

Ich wollte wissen ob es sich noch lohnt die Mühe zu machen den Code mit 
Macros oder Inline zu optimieren oder ob die Compiler das (notfalls mit 
der entsprechenden Compiler-Option) eigenständig machen.
OP (Firma: IGL) #5714293
Lesenswert?

1
 gcc -O1 testgcc.c
 hat es dann gebracht.

Unoptimiert brauchten sowohl gcc und VC jeweils ca. 1200ms für die 
Schleifen.
Die Macros und die Inline-Funktionen brachten in etwa die gleichen 
Ergebnisse wie in den Test zuvor.

Alle bekannten Compiler-Optionen brachten bei VC nicht viel. Das kenne 
ich von früher her anders...

Aber mit der o. g. Option -O1 beim gcc gings dann richtig ab.
15 ms sowohl für Makro-Funktion als auch für die Inline-Funktion.
Die Ergebnisse wurden berechnet.

Das erscheint mir ein bisschen schnell...
#5714330
Lesenswert?

Andreas V. schrieb:
>
1
 gcc -O1 testgcc.c
 hat es dann gebracht.
>
> Unoptimiert brauchten sowohl gcc und VC jeweils ca. 1200ms für die
> Schleifen.
> Die Macros und die Inline-Funktionen brachten in etwa die gleichen
> Ergebnisse wie in den Test zuvor.
>
> Alle bekannten Compiler-Optionen brachten bei VC nicht viel. Das kenne
> ich von früher her anders...
>
> Aber mit der o. g. Option -O1 beim gcc gings dann richtig ab.
> 15 ms sowohl für Makro-Funktion als auch für die Inline-Funktion.
> Die Ergebnisse wurden berechnet.
>
> Das erscheint mir ein bisschen schnell...

Der Code sagt eigentlich nur: es wird jeweils n-mal die gleiche 
Berechnung durchgeführt, die ein konstantes Ergebnis hat, das noch nicht 
einmal weiterverwendet wird. Der Compiler muß noch nichtmal x auf den 
Wert cmax setzen, denn x existiert ja jeweils nur innerhalb der 
Schleifen. Die kürzestmögliche Übersetzung der Schleifen hat exakt 0 
Byte und jeder Compiler, der mehr daraus macht, ist nicht auf der Höhe 
der Zeit. Nicht umsonst gibt es mit volatile die Möglichkeit dem 
Compiler mitzuteilen, daß Dinge passieren können, die er nicht sehen 
kann.

N-mal konstante Werte beliebig kompliziert in ein nicht weiter 
interessierendes Ergebnis zu verrechnen sollte immer exakt 0 beliebige 
Zeiteinheiten dauern. Auch für sehr große N.
#5714622
Lesenswert?

>> Andreas V. schrieb:
>> gcc -O1 testgcc.c  hat es dann gebracht.
>
> Warum nimmst du "-O1" und nicht "-O3" oder "-O2"?
Erst einmal wäre für mich die Frage wofür "-O1" steht?
Laut manpages gcc Option für 'Level', was immer man sich darunter 
vorstellen darf - denn mehr findet man dort nicht.
Welche der rund 600 mehr oder weniger gut dokumentierten Optionen ist es 
denn nun?
https://www-user.tu-chemnitz.de/~hmai/gcc/Ausarbeitung_1/options.html

Weiterhin würde mich interessieren welche Compilerversion Du unter 
CodeBlocks benutzt?
Das alles 'Zufall' beim Compilieren und anschließender Ausführung sein 
soll, glaube ich nämlich nicht.
OP (Firma: IGL) #5714636
Lesenswert?

Carl D. schrieb:
> Der Code sagt eigentlich nur: es wird jeweils n-mal die gleiche
> Berechnung durchgeführt, die ein konstantes Ergebnis hat, das noch nicht
> einmal weiterverwendet wird. Der Compiler muß noch nichtmal x auf den
> Wert cmax setzen, denn x existiert ja jeweils nur innerhalb der
> Schleifen. Die kürzestmögliche Übersetzung der Schleifen hat exakt 0
> Byte und jeder Compiler, der mehr daraus macht, ist nicht auf der Höhe
> der Zeit. Nicht umsonst gibt es mit volatile die Möglichkeit dem
> Compiler mitzuteilen, daß Dinge passieren können, die er nicht sehen
> kann.
>
> N-mal konstante Werte beliebig kompliziert in ein nicht weiter
> interessierendes Ergebnis zu verrechnen sollte immer exakt 0 beliebige
> Zeiteinheiten dauern. Auch für sehr große N.

Ich habe noch einmal eine Operation hinzugefügt (are = are + 1;) und die 
Bit-Schiebeaktion weggelassen. Es sind jetzt so oder so keine 
Konstanten. Man sollte auch beachten dass die Parameter "Call by 
Reference" übergeben werden und nicht "Call by Value". Die Werte werden 
also weiterverwendet.

Die Zeitwerte haben sich nicht wesentlich geändert!
1
#ifndef cmuls
2
#define cmuls(dre, dim, are, aim, bre, bim) \
3
do { \
4
  int32_t tre; \
5
  are = are + 1; \
6
  (tre) = (int32_t)(((int64_t)(are)* (int64_t)(bre)-(int64_t)(aim)* (int64_t)(bim)) ); \
7
  (dim) = (int32_t)(((int64_t)(are)* (int64_t)(bim)+(int64_t)(aim)* (int64_t)(bre)) ); \
8
  (dre) = tre; \
9
} while (0)
10
#endif
11

12
inline void cmuls2(int32_t* dre, int32_t* dim, int32_t* are, int32_t* aim, int32_t* bre, int32_t* bim)
13
{
14
  int32_t tre; 
15
  *are = *are + 1;  
16
  (tre) = (int32_t)(((int64_t)(*are)* (int64_t)(*bre)-(int64_t)(*aim)* (int64_t)(*bim)) ); 
17
  (*dim) = (int32_t)(((int64_t)(*are)* (int64_t)(*bim)+(int64_t)(*aim)* (int64_t)(*bre)) ); 
18
  (*dre) = tre; 
19
}
20

21
void cmuls3(int32_t* dre, int32_t* dim, int32_t* are, int32_t* aim, int32_t* bre, int32_t* bim)
22
{
23
  int32_t tre;
24
  *are = *are + 1;
25
  (tre) = (int32_t)(((int64_t)(*are)* (int64_t)(*bre) - (int64_t)(*aim)* (int64_t)(*bim)) );
26
  (*dim) = (int32_t)(((int64_t)(*are)* (int64_t)(*bim) + (int64_t)(*aim)* (int64_t)(*bre)) );
27
  (*dre) = tre;
28
}
OP (Firma: IGL) #5714642
Lesenswert?

S. R. schrieb:
> Andreas V. schrieb:
>> gcc -O1 testgcc.c  hat es dann gebracht.
>
> Warum nimmst du "-O1" und nicht "-O3" oder "-O2"?

Ich verwende solche Optionen mit Vorsicht. Da muss man aufpassen dass 
nichts wegoptimiert wird. In der Praxis würde ich so etwas nur verwenden 
wenn es nicht anders geht.
Ich kenne bessere Arten seine Zeit zu verbringen...
OP (Firma: IGL) #5714645
Lesenswert?

A. K. schrieb:
> S. B. schrieb:
>> Welche der rund 600 mehr oder weniger gut dokumentierten Optionen ist es
>> denn nun?
>> https://www-user.tu-chemnitz.de/~hmai/gcc/Ausarbeitung_1/options.html
>
> Direkt an der Quelle wirds genauer als in Chemnitz:
> 
https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Optimize-Options.html#Optimize-Options

Und was bedeutet das für mich? Ab welcher Optimierung wird es unsinnig?

Eine Optimierung um das 1000-fache schneller. Da gibt es doch 
Nebeneffekte! Oder?
#5714668
Lesenswert?

Andreas V. schrieb:
> Eine Optimierung um das 1000-fache schneller. Da gibt es doch
> Nebeneffekte! Oder?

Wie man in den Wald reinruft, so schallt es zurück. Bei Testcode muss 
man drauf achten, dass es nicht ausreicht, den Compiler das Endergebnis 
selbst ermitteln zu lassen. Sonst setzt der dieses Endergebnis in den 
Code rein, nicht den Algorithmus.

Solche Optimierungen sind sinnvoller als mancher annimmt. Denn ein 
Nebeneffekt von Konstanten statt Variablen als Parameter solcher Makros 
oder Funktionen ist eine mögliche Vereinfachung der Berechnung. Das 
kommt in realem Code öfter vor und ist genauso richtig.

Ein weiterer Nebeneffekt ist, dass bei laut Standard nicht klar 
definiertem Ergebnis der Compiler etwas anders rechnen könnte als die 
Maschine.
#5714673
Lesenswert?

Andreas V. schrieb:
> Das erscheint mir ein bisschen schnell...

Andreas V. schrieb:
> Da gibt es doch
> Nebeneffekte! Oder?

Es ist schon erstaunlich, wie moderne Compiler optimieren können!
Im Studium habe ich mal einen Equalizer in C implementiert, der bestand 
aus kaskadierten Filtern mit jeweils einigen Additionen/Multiplikationen 
pro Stufe.
Während ich selbst mit allen mir bekannten Tricks die Laufzeit im 
Vergleich zur nicht-optimierten Implementierung nur halbieren konnte, 
hat der gcc sie mit gesetztem Optimierungsflag auf unter 1% gedrückt.
Habe ich dann ungläubig dem Prof. gezeigt, er war aber wenig überrascht 
und meinte nur, dass vernünftige Compiler heutzutage besser optimieren 
als die meisten "Experten".
#5714674
Lesenswert?

A. K. schrieb:
> Solche Optimierungen sind sinnvoller als mancher annimmt. Den ein
> Nebeneffekt von Konstanten statt Variablen als Parameter solcher Makros
> oder Funktionen ist eine mögliche Vereinfachung der Berechnung. Das
> kommt in realem Code öfter vor und ist genauso richtig.


Hier ein Beispiel über dass ich gestern gestolpert bin:

1
// The macros below are derived from the ones above and are used to
2
// check for more specific object types.
3
// Note: these are kept as macros because inline functions sometimes use much
4
// more code space than the equivalent macros, depending on the compiler.
5

6
#define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type == (t))) // this does not work for checking int, str or fun; use below macros for that
7
#define MP_OBJ_IS_INT(o) (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int))
8
#define MP_OBJ_IS_STR(o) (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str))
9
#define MP_OBJ_IS_STR_OR_BYTES(o) (MP_OBJ_IS_QSTR(o) || (MP_OBJ_IS_OBJ(o) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->binary_op == mp_obj_str_binary_op))
10
#define MP_OBJ_IS_FUN(o) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function))

Folgende Zeilen stammen direkt aus dem MicroPython Repo:
https://github.com/micropython/micropython/blob/master/py/obj.h#L258

/edit
Man beachte das Kommentar!
Gast #5714678
Lesenswert?

mh schrieb:
> Andreas V. schrieb:
>> Eine Optimierung um das 1000-fache schneller. Da gibt es doch
>> Nebeneffekte! Oder?
>
> Wenn du dich an die Regeln hältst, gibt es keine Nebeneffekte.

Wenn ich dich bisher richtig verstanden habe, benutzt du die Sprache c. 
Du musst dich also an die Regeln der Sprache c halten?!?
OP (Firma: IGL) #5714681
Lesenswert?

mh schrieb:
> mh schrieb:
>> Andreas V. schrieb:
>>> Eine Optimierung um das 1000-fache schneller. Da gibt es doch
>>> Nebeneffekte! Oder?
>>
>> Wenn du dich an die Regeln hältst, gibt es keine Nebeneffekte.
>
> Wenn ich dich bisher richtig verstanden habe, benutzt du die Sprache c.
> Du musst dich also an die Regeln der Sprache c halten?!?

Also ich kann mich daran erinnern dass da unter Umständen 
Typenprüfungen, Overflows usw. nicht mehr geprüft werden...
Gast #5714710
Lesenswert?

Andreas V. schrieb:
> mh schrieb:
>>> Was kann man an so einfachen Berechnungen und Schleifen
>>> wegoptimieren
>>> außer Überprüfungen, Exceptions, ..?
>>
>> Die ganze Schleife, wenn niemand das Ergebnis anguckt.
>
> Ganz genau!

Wo ist dann dein Problem? Die Aussagekraft deines "Benchmarks" geht auch 
gegen 0, wenn die Schleife nicht wegoptimiert wird.
OP (Firma: IGL) #5714731
Lesenswert?

mh schrieb:
> Wo ist dann dein Problem? Die Aussagekraft deines "Benchmarks" geht auch
> gegen 0, wenn die Schleife nicht wegoptimiert wird.

Ich habe mich nur gefragt warum man C-Macros verwendet, wenn es 
Inline-Funktionen und Compiler-Optionen gibt.

Das Macro ist nicht von mir und wahrscheinlich sehr alt. Außerdem 
gefällt mir die (Typen-)Deklaration/Definition nicht. Das do-while 
Konstrukt kann ich mir nur so erklären dass der Compiler es damals 
anders nicht genommen hat. Warum das Macro schnreller ist und kleiner im 
Code umgesetzt wird hängt meiner Meinung nach damit zusammen dass mit 
den Typen, Überläufen, Exceptions,... weniger strict verfahren wird.

Liege ich falsch?
1
#ifndef cmuls
2
#define cmuls(dre, dim, are, aim, bre, bim) \
3
do { \
4
  int32_t tre; \
5
  are = are + 1; \
6
  (tre) = (int32_t)(((int64_t)(are)* (int64_t)(bre)-(int64_t)(aim)* (int64_t)(bim)) ); \
7
  (dim) = (int32_t)(((int64_t)(are)* (int64_t)(bim)+(int64_t)(aim)* (int64_t)(bre)) ); \
8
  (dre) = tre; \
9
} while (0)
10
#endif
OP (Firma: IGL) #5714739
Lesenswert?

A. K. schrieb:
> Andreas V. schrieb:
>> Das do-while
>> Konstukt kann ich mir nur so erklären dass der Compiler es damals anders
>> nicht genommen hat.
>
> Bei
>   #define MACRO(x) { ... }
>
>   if (cond)
>     MACRO(x);
>   else
>     unsinn();
> gibts einen Syntaxfehler, weil das ";" zu viel ist. Bei
>   #define MACRO(x) do{ ... }while(0)
> passt es.

Mir gehen Macros auch aufn Keks...
OP (Firma: IGL) #5714764
Lesenswert?

> Hier ein Beispiel über dass ich gestern gestolpert bin:
>
> // The macros below are derived from the ones above and are used to
> // check for more specific object types.
> // Note: these are kept as macros because inline functions sometimes use
> much
> // more code space than the equivalent macros, depending on the
> compiler.
>
> #define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) &&
> (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type == (t))) // this does not work
> for checking int, str or fun; use below macros for that
> #define MP_OBJ_IS_INT(o) (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o,
> &mp_type_int))
...
> Man beachte das Kommentar!

Typensicherheit ADE!

Wenn ich so etwas sehe dann will ich mich nur noch erschießen...
#5715318
Lesenswert?

Andreas V. schrieb:
> Ich habe mich nur gefragt warum man C-Macros verwendet, wenn es
> Inline-Funktionen und Compiler-Optionen gibt.

Ganz einfach - weil es Menschen gibt, die wie folgt denken:

Andreas V. schrieb:
>>> gcc -O1 testgcc.c  hat es dann gebracht.
>> Warum nimmst du "-O1" und nicht "-O3" oder "-O2"?
>
> Ich verwende solche Optionen mit Vorsicht.
> Da muss man aufpassen dass nichts wegoptimiert wird.
> In der Praxis würde ich so etwas nur verwenden
> wenn es nicht anders geht.

Konkret: Wenn du Optimierungen abschaltest, weil du Angst davor hast, 
dann bist du mit dem Makro deutlich besser dran als mit dem besten 
Compiler der Welt, denn du hast ihm ja die Optimierungen verboten.
#5715350
Lesenswert?

> Ich frage mich halt nur warum man solche "#define" Definitionen für
> Funktionen wie oben heute noch macht. Mal abgesehen davon dass der
> Debugger streikt.

Das geht natürlich auch als Inline Function. Inline Functions werden 
allerdings wie normale Funktionen realisiert wenn man ohne Optimierungen 
compiliert.

Das ganze als Macro zu definieren erzwingt das inlining und kann dadurch 
auch im Debug Build eine akzeptable Geschwindigkeit erzielen.

Ja, das ist beim debuggen blöd, aber wenigstens hat man eine Chance zu 
debuggen.
#5715475
Lesenswert?

Andreas V. schrieb:
> S. R. schrieb:
>> Andreas V. schrieb:
>>> gcc -O1 testgcc.c  hat es dann gebracht.
>>
>> Warum nimmst du "-O1" und nicht "-O3" oder "-O2"?
>
> Ich verwende solche Optionen mit Vorsicht. Da muss man aufpassen dass
> nichts wegoptimiert wird. In der Praxis würde ich so etwas nur verwenden
> wenn es nicht anders geht.

Wenn was wegoptimiert wird, das eigentlich notwendig wäre, hat das 
Programm einen Fehler.

Andreas V. schrieb:
> mh schrieb:
>> Wenn du dich an die Regeln hältst, gibt es keine Nebeneffekte.
>
> Welche Regeln? ;-)

Na die von C.

Andreas V. schrieb:
> Ich habe keine Angst, aber nur begrenzt Zeit alle Funktionen
> nachzuprüfen!
> Es wäre nicht dass erste Mal dass eine Schleife wegoptimiert wird, oder
> ...

Wie gesagt: Dann ist eigentlich das Programm fehlerhaft, und du hast den 
Fehler durch Unterdrücken der Optimierungen nur versteckt. Das ist 
meiner Meinung nach keine gute Herangehensweise.
#5715481
Lesenswert?

Andreas V. schrieb:
> Ich habe keine Angst, aber nur begrenzt Zeit alle Funktionen
> nachzuprüfen!

Also hast du Angst, dass der Compiler irgendwas mit deinem Code macht, 
was du nicht willst...

Andreas V. schrieb:
> Es wäre nicht dass erste Mal dass eine Schleife wegoptimiert
> wird, oder ...

...was bedeutet, dass dein Code schlicht fehlerhaft ist.
Oder bist du tatsächlich darauf angewiesen, dass überflüssige Schleifen 
in deinem Code tatsächlich zur Laufzeit ausgeführt werden müssen?
Gast #5715495
Lesenswert?

Andreas V. schrieb:
> Ich habe keine Angst, aber nur begrenzt Zeit alle Funktionen
> nachzuprüfen!

Dann lass dir doch vom Compiler helfen und schalte alle Optimierungen 
und Warnungen an. Wenn der Code dann nicht mehr funktioniert, ist er 
höchstwahrscheinlich falsch. Diese Fehler könnten ja auch mit neuen 
Compiler Versionen oder anderen Konstellationen auch ohne Optimierungen 
doch wieder auftreten.
Code, der nur ohne Optimierung funktioniert, würde ich nie produktiv 
nutzen - wer weiß wann einem diese Mine um die Ohren fliegt! Wenn 
offensichtlich Fehler drin sind, kann man das doch nicht so lassen.
#5715498
Lesenswert?

Rolf M. schrieb:
> Wenn was wegoptimiert wird, das eigentlich notwendig wäre, hat das
> Programm einen Fehler.

ACK! Ich habe sehr sehr selten bis nie ein Problem mit der Optimierung. 
Ohne die wären einige Projekte garnicht vernünftig gelaufen weil einfach 
keine Rechenzeit übrig war in Peak-Situationen. Gut das ist auch etwas, 
was einem die Nase kraus werden lässt, ging aber nicht mehr anders. Oder 
ein Requirement dass eine CPU-Load von xx% nicht überschritten werden 
darf,  hätte sonst nicht eingehalten werden können.
OP (Firma: IGL) #5718011
Lesenswert?

Ich habe eben folgende Zeilen im bzip2 Code gefunden:
1
static
2
int bz_config_ok ( void )
3
{
4
   if (sizeof(int)   != 4) return 0;
5
   if (sizeof(short) != 2) return 0;
6
   if (sizeof(char)  != 1) return 0;
7
   return;
8
}

Bei Optimierung auf Codegröße(/O1) oder Schnelligkeit (/O2) gibt die 
Funktion immer 0 zurück.

sizeof(int) ergibt 0!

Ich kann also nicht mehr zippen!
;-)
#5718039
Lesenswert?

Andreas V. schrieb:
> Ich habe eben folgende Zeilen im bzip2 Code gefunden:
>
>
1
> static
2
> int bz_config_ok ( void )
3
> {
4
>    if (sizeof(int)   != 4) return 0;
5
>    if (sizeof(short) != 2) return 0;
6
>    if (sizeof(char)  != 1) return 0;
7
>    return;
8
> }
9
>
>
> Bei Optimierung auf Codegröße(/O1) oder Schnelligkeit (/O2) gibt die
> Funktion immer 0 zurück.
>
> sizeof(int) ergibt 0!
>
> Ich kann also nicht mehr zippen!
> ;-)
Die Zeile
1
  return;
Sollte eine Warnung/einen Fehler produzieren.
Wenn nicht, solltest du die Compilerflags prüfen.

merciless
#5718060
Lesenswert?

900ss D. schrieb:
> Außerdem ist der return-Wert beim letzten Return undefiniert.
> Die Routine ist buggy.

Offensichtlich hat er den Code fehlerhaft abgetippt (Copy&paste 
anyone?), denn das Original lt. Sourceforge sieht anders aus:
1
static
2
int bz_config_ok ( void )
3
{
4
   if (sizeof(int)   != 4) return 0;
5
   if (sizeof(short) != 2) return 0;
6
   if (sizeof(char)  != 1) return 0;
7
   return 1;
8
}

Schnell überflogen ist rätselhaft, was da wegoptimiert werden soll.

Andreas V. schrieb:
> sizeof(int) ergibt 0!

Mit Sicherheit nicht. Woher nimmst du diese Weißheit?

Andreas V. schrieb:
> Bei Optimierung auf Codegröße(/O1) oder Schnelligkeit (/O2)

O1 und O2 ist beides auf Geschwindigkeit. Os ist Codegröße, beim GCC 
jedenfalls.
#5718234
Lesenswert?

vn n. schrieb:
> Schnell überflogen ist rätselhaft, was da wegoptimiert werden soll.

Der Compiler kann sämtliche sizeof() zur Compilezeit ausrechnen und dann 
die gesamte Funktion wegoptimieren.

Auf manchen Architekturen (z.B. AVR) ist sizeof(int) == 2, dann gibt die 
Funktion immer 0 zurück. Alle auch nur ansatzweise üblichen 
Architekturen, wo das nicht der Fall ist, haben sizeof(int) == 4.

Wenn da was anderes rauskommt, ist höchstwahrscheinlich der Compiler 
kaputt.

Aber ich glaube, der TO will uns nur ein (doofes) Beispiel für "der 
Compiler optimiert meine Funktion weg und das will ich nicht" zeigen. 
Was natürlich schon in sich relativ bescheuert ist, aber das ist ja 
nicht mein Problem.
#5718235
Lesenswert?

Andreas V. schrieb:
> Ich habe es mir im Debugger ausgeben lassen.

Also du bist schrittweise durch die Funktion gesteppt?
Wenn du den Compiler optimieren läst, dann passen die 
Zeileninformationen nicht mehr zum Sourcecode und es kommt erstmal 
wirres beim debuggen raus.
Du müsst dir das Ergebnis von der Funktion mit printf oder sonst wie 
ausgeben lassen.
Gast #5718266
Lesenswert?

Andreas V. schrieb:
> A. K. schrieb:
>> Inline-Funktionen sind eleganter.
>
> Inline ist doch ein C++ Keyword oder?

Njein,

"inline" ist relativ neu im C-Standard; es wurde eingeführt in "section 
6.7.4 of the C99 standard (ISO/IEC 9899:1999)". Verschiedene Compiler 
wie der gcc kannten es schon bevor es Standard wurde (1999).

Da MPEG aber älter ist (1991), könnte das der Grund sein, warum man sich 
für die unelegantere aber steinzeitkompatiblevariante entschied. Falls 
es mangels der "inline"-Unterstützung der damaligen Compiler überhaupt 
eine Entscheidungsmöglichkeit gab.
Gast #5718294
Lesenswert?

S. R. schrieb:
> Der Compiler kann sämtliche sizeof() zur Compilezeit ausrechnen und dann
> die gesamte Funktion wegoptimieren.

Natürlich kann er das, aber es erklärt nicht warum es dann nicht 
funktionieren soll, so war das gemeint.

S. R. schrieb:
> Auf manchen Architekturen (z.B. AVR) ist sizeof(int) == 2, dann gibt die
> Funktion immer 0 zurück. Alle auch nur ansatzweise üblichen
> Architekturen, wo das nicht der Fall ist, haben sizeof(int) == 4.

Klar, wobei das eine denkbar doofe Lösung ist, könnte man seit C99 
immerhin auch einfach uint32_t nehmen.

S. R. schrieb:
> Aber ich glaube, der TO will uns nur ein (doofes) Beispiel für "der
> Compiler optimiert meine Funktion weg und das will ich nicht" zeigen.
> Was natürlich schon in sich relativ bescheuert ist, aber das ist ja
> nicht mein Problem.

Vermutlich, oder er will einfach nur trollen.
Gast #5718297
Lesenswert?

vn n. schrieb:
> Er meinte ja gegenüber Funktionsaufrufen. Da spart es tatsächlich,  wenn
> Funktionen nicht geinlined werden (z.B. mit -O0 kompiliert).

Es es nicht nur der Aufruf der Funktion, der Compiler kann dann besser 
optimieren. Das gilt sowohl für Makros und für inline.
Gast #5718312
Lesenswert?

Natürlich kann er das, aber was hat das mit meinem Posting zu tun?
Die Sache mit dem Macro ist drinnen weil damals Compiler oftmals nicht 
mal inlinen konnten, da brauchte man über weitergehende Optimierungen 
nicht mal nachdenken. Dass er das heute schon kann, wurde ja schon zu 
genüge geklärt.
OP (Firma: IGL) #5718406
Lesenswert?

Rolf M. schrieb:
> Gib es mit z.B. printf aus. Die Ausführung von optimiertem Code im
> Debugger hat ihre Tücken.

Ich lache mich tot.
Ich hatte vorher schon einen kompletten cleanup gemacht und alles neu 
kompiliert. Es funzte nicht.

Nur wenn ich die Werte mit printf ausgebe springt das Programm nicht zum 
Exit. Ist halt nur blöd wenn man mal ein Gerät hat das kein printf 
kennt.

Ja schon klar über serial Port, aber denn will man ja vielleicht 
nicht....

Die IDE war mir abgestürzt...
#5718421
Lesenswert?

Andreas V. schrieb:
> Rolf M. schrieb:
>> Gib es mit z.B. printf aus. Die Ausführung von optimiertem Code im
>> Debugger hat ihre Tücken.
>
> Ich lache mich tot.
> Ich hatte vorher schon einen kompletten cleanup gemacht und alles neu
> kompiliert. Es funzte nicht.
>
> Nur wenn ich die Werte mit printf ausgebe springt das Programm nicht zum
> Exit. Ist halt nur blöd wenn man mal ein Gerät hat das kein printf
> kennt.
>
> Ja schon klar über serial Port, aber denn will man ja vielleicht
> nicht....

Es ist doch ganz einfach: Wenn du ein sizeof(int) machst, es aber 
nirgends im Programm benutzt, dann ist es nutzlos und wird vom Compiler 
wegoptimiert. Sobald du es auch benutzt, passiert das natürlich nicht 
mehr. Der Optimizer ist ja gerade dafür da, alles rauszuwerfen, was 
nicht benötigt wird. Deshalb kommt natürlich auch Blödsinn raus, wenn du 
Code schreibst, dessen Ergebnis du im Programm gar nicht benutzt und 
dann im Debugger anschaust, welcher Wert rauskommt. Für das Programm 
spielt der Wert keine Rolle, da es ihn sowieso verwirft. Baust du das 
printf ein, dann wird der Wert benötigt, da er ja ausgegeben werden 
muss, also kann er nicht mehr wegoptimiert werden.
Gast #5718725
Lesenswert?

Andreas V. schrieb:
> Dann kann ich bz_config_ok ja auskommentieren.

Oder direkt zur Compile-Zeit prüfen:
1
#include <assert.h>
2

3
static_assert (sizeof(int) == 4, "Int muss 4 bytes sein");
4
static_assert (sizeof(short) == 2, "Short muss 2 bytes sein");
5
static_assert (sizeof(char) == 1, "Char muss 1 bytes sein");

Die letzte Prüfung ist natürlich sinnlos - sizeof(char) ist immer 1, 
auf jeder Plattform. Die Einheit, in der sizeof die Größe zurückgibt, 
sind Vielfache von der Größe von char - und 1 char ist nunmal genau 1 
char groß.

Noch besser ist aber natürlich auch die Verwendung von (u)int16_t und 
(u)int32_t. sizeof() übrigens gibt nie 0 zurück.
#5725177
Lesenswert?

Dr. Sommer schrieb:
> Die letzte Prüfung ist natürlich sinnlos - sizeof(char) ist immer 1,
> auf jeder Plattform. Die Einheit, in der sizeof die Größe zurückgibt,
> sind Vielfache von der Größe von char - und 1 char ist nunmal genau 1
> char groß.

Höchstens einen kaputten Compiler könnte man damit noch detektieren, 
aber so dermaßen kaputt wird wohl keiner sein.

Dr. Sommer schrieb:
> Noch besser ist aber natürlich auch die Verwendung von (u)int16_t und
> (u)int32_t.

Heute (damals gab es die vielleicht noch nicht, je nachdem von wann der 
Code ist) wäre dies sogar die einzig sinnvolle Variante.
Denn der Code macht dies ja vermutlich um sicherzustellen dass char == 
8bit, short == 16bit und int == 32bit ist. Blöderweise gibt es aber auch 
Plattformen auf denen gilt char == 16bit (für so eine schreib ich 
gerade). Wäre dort short == 32bit und int == 64bit (sind sie in meinem 
konkreten Fall nicht, wäre aber durchaus denkbar) wäre die Bedingung der 
sizeofs trotzdem erfüllt.
Gast #5725178
Lesenswert?

vn n. schrieb:
> Wäre dort short == 32bit und int == 64bit (sind sie in meinem
> konkreten Fall nicht, wäre aber durchaus denkbar) wäre die Bedingung der
> sizeofs trotzdem erfüllt.

Richtig. Daher muss man zusätzlich prüfen ob CHAR_BIT = 8 ist. Das wäre 
deutlich sinnvoller als sizeof(char)=1 zu prüfen.

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