Jeśli a=2, to a++ + ++a == 42?
Każdy egzamin z programowania w C ma pytania zamknięte. Wierz mi... rozumiem Cię i wiem, co czujesz, gdy je widzisz.
Niewielu ludzi rozumie, co tak naprawdę kryje się za tymi pytaniami, a mimo to ciągle je zadają.
Jeśli a=2
to jaka będzie wartość ++a + a++ + a++
?
Niektórzy posuwają się nawet tak daleko, że piszą instrukcje, które nie mieszczą się na jednej stronie A4.
a = a++ + ++a + a++ + a++ + ++a
... i tak dalej.
Ogólnie, jeśli a=2
to a++ + ++a
może być równe 2, 4, 5, 42, 99, 2048 i tak dalej. W takich sytuacjach kompilator może wypluć co mu się żywnie podoba. Jaka jest tutaj zasada?
Niektórzy z was mogą myśleć, że odpowiedź na wyżej postawione pytanie jest zależna od kompilatora lub jest nie do przewidzenia.
Jak zatem do tego podejść?
No więc w C istnieje coś takiego, jak sequence point. Po każdym takim punkcie w sekwencji kompilator ocenia, co tak naprawdę napotkał po poprzednim sequence point.
Tak więc średnik (; ASCII 59) jest sequence pointem w C. Kompilator ocenia wszystko kiedy napotka ten średnik przed wykonaniem kolejnej instrukcji.
Jeśli mamy coś takiego:
int numberOne = 2, numberTwo=3;
sum = numberOne + numberTwo;
printf(“%d”, sum);
to wydrukowana suma będzie wynosić 5, ponieważ kompilator oceni sumę w drugim wyrażeniu zanim przejdzie do printf
.
Jednak sposób, w jaki kompilator wykonuje rzeczy wewnątrz sekwencji, nie jest gwarantowany. Weźmy np. poniższe wyrażenie:
i = j++ + k++;
Nikt nie może przewidzieć, co zostanie zinkrementowane jako pierwsze: j
czy k
. Chociaż czasami to nie ma znaczenia. Jednak w niektórych przypadkach może to np. obniżyć średnią ocen studenta.
Ale co z niezdefiniowanym zachowaniem?
Standardy języka C zakładają, że wartość zmiennej może się zmienić najwyżej raz w pojedynczym sequence point. W wyrażeniach pokroju a++ + ++a
zmieniamy jednak wartość a więcej niż jeden raz. Kompilator języka C na to nie pozwala. Jeśli Ty łamiesz zasady, to kompilator też je złamie.
Więc jeśli kiedykolwiek spotkasz się z takim pytaniem, najwłaściwszą odpowiedzią będzie: nie do przewidzenia, albo zależny od kompilatora. Jeśli nie ma takiej odpowiedzi, porozmawiaj ze swoim wykładowcą i grzecznie wskaż mu ten blog.