AmigaE wykonuje odejmowanie przed dzieleniem/mnożeniem, bo nie ma priorytetów operacji i wszystko robi jak leci, od lewej do prawej, a nie zgodnie z zasadami.
np. w AmigaE 4-8/4 = (4-8)/4 = -1 :D
Wykrzyknik.
Zapisany przed wyrażeniem:
c:=!a+b; b:=!c+1.0; d:=!a+b*d
Oznacza, że operacja będzie wykonywana jako zmiennoprzecinkowa i tak też potraktowane zostaną zmienne. W ostatnim przykładzie też nie jest brana pod uwagę kolejność wykonywania, więc najpierw będzie dodawanie, a potem mnożenie
Istnieje jeszcze taki zapis: a:=!b, dla kompilatora nie ma on kompletnie żadnego znaczenia, oznacza tylko, że b jest zmiennoprzecinkowe, ale to i tak bez różnicy, bo wszystko jest traktowane jako LONG, w sumie to tak tylko dla użytkownika, żeby wiedział, że to na zmiennym przecinku jest liczone.
Podobnie w zapisie: IF !a>b; wykrzyknik oznacza, że porównywane będą liczby zmiennoprzecinkowe.
zapisany po zmiennej, albo wyrażeniu w nawiasie (dokładnie to chodzi o 'semantic value' ostatniego tokenu na stosie parsera ;) ):
1) a:=b!
2) c:=(a+b)!
3) c:=a+b!
dokonuje konwersji z typu całkowitego na zmiennoprzecinkowy
w pierwszym przykładzie całkowita wartość b zostanie zamieniona na zmiennoprzecinkową i przypisana do a
W przykładzie drugim wyrażenie a+b zostanie obliczone jako CAŁKOWITE i dopiero wynik zostanie zamieniony na postać zmiennoprzecinkową i przypisany do c.
Ostatni przykład jest błędny - wartość b zostanie zamieniona na postać zmiennoprzecinkową, następnie zostanie wykonane CAŁKOWITE dodawanie a do zmiennoprzecinkowej postaci b, śmieci zostaną zapisane do c. w tym wypadku kompilator chyba nawet nie zgłosi błędu, bo z ponktu widzenia kompilatora zapis jest całkowicie poprawny i oznacza bezpośrednie operowanie na zapisie zmiennoprzecinkowym (takie sztuczki mogą się czasem przydać, np do szybkiego mnożenia liczb zmiennoprzecinkowych przez potęgi dwójki (również ujemne, czyli dzielenie przez 2^x)- wystarczy tylko odpowiednio operować wykładnikiem liczby zmiennoprzecinkowej)
Wykrzyknik umieszczony przed i po zmiennej/wyrażeniu w () (chodzi o to samo, co powyżej)
1) c:=!b!
2) c:=!(a+b)!
3) c:=!(!a+b)!
4) c:=!a+b!
1) zmiennoprzecinkowa zmienna ;) b zostanie zamieniona na całkowitą, wynik zostanie przypisany do c
2) błąd - wyrażenie a+b zostanie obliczone jako całkowite, a następnie wynik potraktowany jako jiczba zmiennoprzecinkowa (chociaż wcale nią nie jest) i zamieniony na postać całkowitą. śmieci zostaną przypisane do c. Nie jestem pewien, co zrobi z tym kompilator, być może jednak a+b zostanie obliczone jako zmiennoprzecinkowe, ale wątpię, dla bezpieczeństwa warto stosować to tak. jak w przykładzie 3)
3) a+b zostanie obliczone jako zmiennoprzecinkowe, a zmiennnoprzecinkowy wynik zamieniony na postać całkowitą i przypisany do c
4) błąd, albo i nie, zależy jak na to patrzeć. Na pewno nie zostanie wykonana konwersja do typu całkowitego taka pułapka :) ) zmienna b (całkowita) zostanie zamieniona na postać zmiennoprzecinkową, następnie do wyniku konwersji zostanie dodana wartość a (zmiennoprzecinkowe), wynik (też zmiennoprzecinkowy) zostanie przypisany do c
Składnia E jest trochę niejasna, niby jest to opisane, ale dziwny sposób interpretacji wyrażeń przez kompilator to same problemy.
Moja rada - zapisuj wszystko tak, żebyś nie miał wątpliwości, co się dziele np wyrażenie taki oto zapisane w C:
a = (int) ((a+ b + c) * d / (e - (float) (f))); /* wszystkie zmienne, oprócz "f" i "a", zmiennoprzecinkowe)
W AmigaE zapisz tak:
a := !(!(!(!a+b+c)*d) / (!e - (f!)))!
Dużo tych wykrzykników i nawiasów, ale masz przynajmniej pewność, że bedzie działać dokładnie tak, jak Ty chcesz :)
i bardzo ważna rzecz - liczby (stałe) zmiennopzecinkowe MUSZĄ zawierać kropkę, wobec czego zapis: a := !a + 1 jest błędny, poprawne są a:=!a+1.0; a:=!a+1.
Tylko jeszcze pozostaje kwestia nierozstrzygnięta - co lepsze, połapać się w wykrzyknikach i dopilnować nawiasów, czy wpoić sobie zasady interpretacji wyrażeń przez kompilator. Ja wybrałem tą pierwszą opcję i nigdy nie używałem bardziej skomplikowanej składni niż ta w przykładzie.
Duża ilość nawiasów i wykrzykników nie ma wpływu na wydajność, tam, gdzie ma się wykonać konwersja, to się wykona, tam gdzie nie, to nie ;)
moje zaasady zapisu wyrażeń zmiennoprzecinkowych:
wszystkie konwersje LONG->float wrzucam w nawiasy, czyli (a!), (!a!), (!(!a+b)!), ((a+b)!)
jeżeli mam róźne operatory grupuję w osobnych nawiasach np: !(!(!a + b + c) * (!d - e - 1.0) * 2.7) - 1.0. Nie wiem jak to napisać ;) , chodzi o to, żeby nie pisać np. !a+b*c, tylko !a+(!b*c), działa tak samo, ale łatwiej się połapać (przynajmniej mi)
No i to chyba by było na tyle.
Przesiadka na CreativE powinnna być bezbolesna

, różnic prawie brak, a działa lepiej np. w E Woutera kilka rzeczy, które POWINNY działać, po prostu nie działały.
W sumie dlatego przesiadłem się na C, tam jest wszystko jasne. No prawie wszystko i z tej okazji mam super zagadkę (pytanie jak najbardziej poważne):
Jak w C zadeklarować wskaźnik na tablicę wskaźników na struktury?

(wszystko oprócz zawartości struktur jest stałe, znaczy na stałe zafixowane w programie), w asm umiem i ma to wyglądać mniej więcej tak:
SECTION CODE
(...)
wskaznik: LONG tablica
tablica: LONG struktura1, struktura2, struktura3, 0
struktura1: LONG #dana1, #dana2
struktura2: LONG #dana1, #dana2
struktura3: LONG #dana1, #dana2
no i ma to działać tak, że mogę uzyskać swobodny dostęp do już zainicjowanych danych.