Hi
ich habe eine Variable int a und möchte, dass diese maximal den Wert
10000 annimmt, egal wie oft ich a++ rechne. Kann man das irgendwie am
Anfang deklarieren?
Ich schreibe in C
D. I. schrieb:> Was wohl passiert wenn a = 2^31-1 ist?! ;) Ich denke man sollte a nicht> verändern wenn 10000 ereicht wurde.
Eher so:
unsigned int ink(unsigned int a, unsigned int maximum)
{
return (a++ > maximum - 1) ? maximum : a;
}
>> Kann man das irgendwie am Anfang deklarieren?>nein.>> die if anweisung ist perfekt für mich!>Da ist aber nichts am Anfang deklariert.
Ja gerade, weil es nicht geht, muss ich wohl mit der if anweisung
leben...
>> So, und hier die Frage an die C-Standard-Versteher:>> Ist der Rückgabewert davon jetzt a oder a+1 (für a < maximum)?
Der Rückgabewert ist entweder maximum oder der bereits erhöhte Wert.
Beim ? ist ein Sequence Point, damit ist dort die ++ Operation
abgeschlossen.
Naja, vielleicht doch noch eine Variante (angelehnt an die
häufige Implementation von errno über ein Makro und eine Funktion,
die einen Zeiger auf die Variable liefert):
1
#include<stdio.h>
2
3
#define meineVariableA (*aGetAddress())
4
int*aGetAddress()
5
{
6
staticinta=0;
7
if(a>10000)
8
{
9
a=10000;
10
}
11
return&a;
12
}
13
14
15
intmain(intnargs,char**args)
16
{
17
meineVariableA=5;
18
printf("meineVariableA = %d\n",meineVariableA);
19
20
meineVariableA=9999;
21
printf("meineVariableA = %d\n",meineVariableA);
22
23
meineVariableA++;
24
printf("meineVariableA = %d\n",meineVariableA);
25
26
meineVariableA++;
27
printf("meineVariableA = %d\n",meineVariableA);
28
29
meineVariableA++;
30
printf("meineVariableA = %d\n",meineVariableA);
31
32
meineVariableA++;
33
printf("meineVariableA = %d\n",meineVariableA);
34
35
printf("meineVariableA = %d\n",meineVariableA++);
36
printf("meineVariableA = %d\n",meineVariableA++);
37
printf("meineVariableA = %d\n",meineVariableA++);
38
39
printf("meineVariableA = %d\n",++meineVariableA);
40
printf("meineVariableA = %d\n",++meineVariableA);
41
printf("meineVariableA = %d\n",++meineVariableA);
42
43
return0;
44
}
Das funktioniert weitgehend.
Zu beachten ist nur, daß ++meineVariableA einen Wert liefert,
der ggf. 1 über dem Maximum liegt:
>nö, wenn schon dann> a = (a<maximum ? ++a : maximum );
Irgendwie bin ich gerade blind. Was stoert Dich an meiner Version mit
dem Postincrement?
a = (a<maximum ? a++ : maximum );
oder dann
if (a<maximum) a++;
chris schrieb:> Was stoert Dich an meiner Version mit> dem Postincrement?>> a = (a<maximum ? a++ : maximum );
Daß es nicht funktionieren wird (bzw. nicht definiert ist), sonst
ist sie schön.
Das Problem ist die Reihenfolge der Auswertung:
Wenn a noch nicht maximum erreicht hat, geht es in das a++.
Das liefert den alten Wert von a und erhöht anschließend a.
I.d.R. wird dann der alte Wert zugewiesen, damit ist die
Erhöhung für die Katz.
M.W. ist diese Reihenfolge aber nicht sicher, es kann erst
der alte Wert zugewiesen werden und dann die Erhöhung
stattfinden.
chris schrieb:> oder dann>> if (a<maximum) a++;
Das dagegen ist in Ordnung, wenn auch viel zu einfach :-)
Noch eine Variante, die wir noch nicht hatten:
(a<maximum) ? a++ : (a=maximum);
PS: Ich habe es eben mit dem gcc probiert.
Da kommt bei deiner Version der alte Wert raus und eine Warnung:
t.c:24: warning: operation on ‘a’ may be undefined
> Da hätte ich auch noch mal was ganz anderes:> a<maximum && ++a;
Auch nett!
Wobei die beiden Fälle dann merkwürdigerweise etwas ganz
unterschiedliches liefern: entweder die 0 vom Vergleich oder
den neuen Wert von a.
Deshalb würde ich den Rückgabewert sicherheitshalber wegwerfen,
auch wenn es vielen dann vielleicht noch merkwürdiger erscheint:
(void)(a<maximum && ++a);
Der zweite ist ja noch besser :-)
Klaus Wachtler schrieb:> Wobei die beiden Fälle dann merkwürdigerweise etwas ganz> unterschiedliches liefern: entweder die 0 vom Vergleich oder> den neuen Wert von a.
Das stimmt. Da könnte man jetzt aber prima den Komma-Operator einsetzen:
1
a<maximum&&(++a,1);
Dann kommt wie beim Vergleich selber 0 oder 1 raus. ;-)
>a<maximum && ++a;
Oh, das ist aber haarig, wenn auch ziemlich trickreich. Man verlässt
sich ja voll auf die Reihenfolge der Ausführung. Ich frage mich, ob da
nicht ein Optimierer im Compiler was verdrehen könnte.
>Deshalb würde ich den Rückgabewert sicherheitshalber wegwerfen
Die Zeile selbst hat ja keinen Rückgabewert. Deshalb müsste man den Wert
auch nicht wegwerfen, oder?
a<maximum && ++a; hat sehr wohl einen Rückgabewert, nur
verwendet man ihn hoffentlich meistens nicht.
Um eine versehentliche Verwendung zu verhindern (in der
Art: a = a<maximum && ++a) finde ich den cast nach void
angemessen.
chris schrieb:>>a<maximum && ++a;> Oh, das ist aber haarig, wenn auch ziemlich trickreich. Man verlässt> sich ja voll auf die Reihenfolge der Ausführung. Ich frage mich, ob da> nicht ein Optimierer im Compiler was verdrehen könnte.
na und? Das ist vollkommen legal, weil die Reihenfolge beim && und
die short circuit evaluation in C verbindlich sind.
Der Optimierer wird das auch wissen.