[ Everback @ 19.01.2018. 08:59 ] @
Postavite ovde kod koji daje neočekivani rezultat. Bilo koji programski jezik (osim Whitespace).

Nešto jednostavno za početak:
Šta je izlaz programa (odgovor bez pokretanja interpretera u roku od 10 sekundi)?

Code:

<?php 
    $x=1; 
    echo $x + ++$x;

[ CoyoteKG @ 19.01.2018. 10:45 ] @
Nisam programer, ali verovatno neki error, jer ne vidim da se zatvorio taj tag <?php
[ Everback @ 19.01.2018. 10:56 ] @
Ne postoji sintaksna greška. Kod je ispravan. Kod php-a se i ne preporučuje pisanje zatvarajućeg taga ukoliko nije neophodno, jer se može desiti da zbog nekog spejsa iza zatvarajućeg taga nenamerno pošaljemo sadržaj pre hedera...

Rezultat ovog programa je celi broj. Promenljiva x ima inicijalnu vrednost 1. Operator ++ uvećava promenljivu za jedan. Plus sabira vrednosti. Rezultat je _____

P.S.
Napisao sam maločas da bi trebalo da je isti rezultat i kod ostalih jezika iz C familije, pa rekoh da testiram C i JS i rezultat se razlikuje :) C i PHP daju isti rezultat.
[ nemamstan @ 19.01.2018. 11:03 ] @
Unarna operacija dobila prioritet.

Code:
<?php 
    $x=1; 
    echo $x - ++$x;

    $x=1; 
    echo $x - --$x;
?>


Mislim da je to pre ko zna kliko godina opisano u dokumentaciji za php.
[ Everback @ 19.01.2018. 11:07 ] @
Da, zato je prethodno rešenje 4. Zašto je ovde 3?
JS:
Code:

   var x=1;
   alert(x + ++x);
[ nemamstan @ 19.01.2018. 11:28 ] @
Code:
<?php
    $x=1; 
    echo $x ^ 2;
?>
[ Everback @ 19.01.2018. 11:34 ] @
0001
0010
------
0011
[ Everback @ 19.01.2018. 11:41 ] @
Ovde je dovoljno samo da prepoznate o kom programskom jeziku se radi :)
Code:

DO ,1 <- #13
PLEASE DO ,1 SUB #1 <- #238
DO ,1 SUB #2 <- #108
DO ,1 SUB #3 <- #112
DO ,1 SUB #4 <- #0
DO ,1 SUB #5 <- #64
DO ,1 SUB #6 <- #194
DO ,1 SUB #7 <- #48
PLEASE DO ,1 SUB #8 <- #22
DO ,1 SUB #9 <- #248
DO ,1 SUB #10 <- #168
DO ,1 SUB #11 <- #24
DO ,1 SUB #12 <- #16
DO ,1 SUB #13 <- #162
PLEASE READ OUT ,1
PLEASE GIVE UP
[ Cube25 @ 19.01.2018. 11:56 ] @
@everback

Code daje uvek ocekivan rezultat -> jer za razliku od ljudi, ima jasno navedena pravila po kojima se taj rezultat dobija, po kojima radi. Eventaulne greske nastaju kod preciznosti... ali to je neka druga tema.
To sto si ti naveo je primer loseg programiranja. Tj. primer bas kako ne treba da se pise code - jer code na prvom mestu treba da bude jasan. Ne bi bio kraj sveta da je kreirana jos jedna promenjiva, i vishe ne bi bilo razmatranja sta ce biti kako interpretirano i gde.

...

[to state the obvious:]
Ovo je primer right first vs left first evaluacije izraza... Tj. u jednom slucaju racunanje izraza pocinje prvo sa desne strane, gde se inicijalni broj ikrementira za 1 i postaje 2, i posle sabira sam sa sobom, sto je (sada 4, jer je u mejuvremenu postao 2 umesto 1). Dok u drugom slucaju on je 1, i sabira se sa samim sobom inkrementiranim za jedan, tj. sa 2, pa daje 3 kao rezultat.

Opet, idiotski primer (isforsiran), koji sluzi samo da objasni kako kod ne treba da izgleda. Tj. sta da se izbegne, ako se zeli jasan i pravilno napisan kode. Kao i da prikaze razliku izmedju left i right evaluacije izraza.

Obicno se ta evaluacija koristi, kad se zeli ubrzati/napraviti cistiji kode, da se ne pishe pedeset if-ova...


if (mojPointer != null && mojPointer->nekaVrednost < zeljenaVrednost)
{
obavestiMamuDaJeSkuvanaSarma();
}

U tom slucaju left first chekira da li je uopste pointer setovan... pa tek onda u ostatku izraza trazi promenjivu iz njega, ako jeste. Ako nije odma preskace ceo blok. Ali opet, treba znati specificnosti jezika i kompajlera ako se pise takav code. Sigurnije je pisati dva odvojena if-a.





[Ovu poruku je menjao Cube25 dana 19.01.2018. u 13:07 GMT+1]
[ Everback @ 19.01.2018. 12:05 ] @
Ljudi očekuju rezultat, tako da kod ne može da daje uvek očekivani rezultat. Kod nema pojma šta ljudi očekuju. Očekivanja su često nerealna :) Uglavnom, ovo je tema o tome, a ne o dobrom kodu.

P.S.

Ne kaže se idiotski nego idiJotski.

P.P.S.

Samo se zezam, idiotski je ispravno, nije ispravno iZforsiran.
[ Branimir Maksimovic @ 19.01.2018. 14:41 ] @
Citat:
Everback:
Ne postoji sintaksna greška. Kod je ispravan. Kod php-a se i ne preporučuje pisanje zatvarajućeg taga ukoliko nije neophodno, jer se može desiti da zbog nekog spejsa iza zatvarajućeg taga nenamerno pošaljemo sadržaj pre hedera...

Rezultat ovog programa je celi broj. Promenljiva x ima inicijalnu vrednost 1. Operator ++ uvećava promenljivu za jedan. Plus sabira vrednosti. Rezultat je _____

P.S.
Napisao sam maločas da bi trebalo da je isti rezultat i kod ostalih jezika iz C familije, pa rekoh da testiram C i JS i rezultat se razlikuje :) C i PHP daju isti rezultat.


Ne znam za PHP, ali u C-u ti je to undefined behavior. Dvaput menjanje vrednosti varijable bez intervenieng sequence poijnt ;)
eidt:
Zapravo nisam siguran posto samo printas, najverovatnije je ok ;)
[ Bojan Basic @ 19.01.2018. 14:54 ] @
Citat:
Everback:
Da, zato je prethodno rešenje 4.

Zapravo, nije izvesno da će rezultat biti 4. Svakako ++ ima prednost nad +, što znači da će svakako sabiranje biti izvršeno nakon ++, ali pitanje je koje dve vrednosti će biti sabrane, tj. da li će vrednost levog $x biti uzeta u obzir pre ili posle primene ++ (što nije ni u kakvoj vezi s prioritetom ++ u odnosu na +). Pogledaj ovde:
Citat:
Operator precedence and associativity only determine how expressions are grouped, they do not specify an order of evaluation. PHP does not (in the general case) specify in which order an expression is evaluated and code that assumes a specific order of evaluation should be avoided, because the behavior can change between versions of PHP or depending on the surrounding code.
[ Branimir Maksimovic @ 19.01.2018. 15:05 ] @
Code:

interv.c: In function ‘main’:
interv.c:5:23: warning: operation on ‘x’ may be undefined [-Wsequence-point]
     printf("%d\n",x + ++x);


Zapravo jeste undefined behavior kako sam pretpostavio ;p
[ Everbeck @ 19.01.2018. 15:23 ] @
@Bojan
Ok, onda ovo jeste definitivno kod koji proizvodi neočekivani rezultat, a sada je jasno i zašto JS daje vrednost 3.

@Branimir Maksimovic
Kod mene je prošlo kompajliranje i rezultat je 4. Kompajler je gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609. Sigurno je da i kod C-a rezultat zavisi od implementacije kompajlera. Čini mi se da je u poslednjim verzijama c++ standarda to definisano.

Kada sam već tu, čudni kod nešto iznad je Intercall i prikazan je najjednostavniji način kako da se u ovom programskom jeziku ispiše na konzoli Hello word. Naravno ja ne znam Intercall.
[ Branimir Maksimovic @ 19.01.2018. 15:40 ] @
Undefined behavior je greska u run-time ;)
Ja sam kompajlirao sa gcc-trunk i to je najsveziji moguci koji ti cak daje warninge i o nedefinisanom ponasanju ;p
[ mjanjic @ 19.01.2018. 20:21 ] @
Citat:
Code:

<?php 
    $x=1; 
    echo $x + ++$x;




Code:
Finding entry points
Branch analysis from position: 0
Jump found. (Code = 62) Position 1 = -2
filename:       /in/OIeIG
function name:  (null)
number of ops:  6
compiled vars:  !0 = $x
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   3     0  E >   ASSIGN                                                   !0, 1
   4     1        PRE_INC                                          $2      !0
         2        ADD                                              ~3      !0, $2
         3        CONCAT                                           ~4      ~3, '%0A'
         4        ECHO                                                     ~4
         5      > RETURN                                                   1

Generated using Vulcan Logic Dumper, using php 7.1.0


Očigledno, kao što su neki rekli, inkrementiranje ima prioritet.
[ mjanjic @ 19.01.2018. 20:22 ] @
Međutim, interesantno je da sledeći kod radi normalno:
Code:
<?php 
    $x=1; 
    echo $x+++$x;
[ Branimir Maksimovic @ 19.01.2018. 20:37 ] @
Kako parsuje +++ ?
[ Everbeck @ 19.01.2018. 21:11 ] @
Verovatno kao $x++ +$x
[ damirh @ 19.01.2018. 23:25 ] @
meni je zanimljivije da eclipse dozvoljava
Code:
int x=1; 
System.out.println(x+++x);

gde ne zna da li hocu x++ ili ++x
a ne dozvoljava
Code:
int x=1; 
System.out.println(1+++x);

gde bi mu bilo jasno da sigurno ne mislim 1++ dok je 1+ ++x sasvim legitimno

a x++ +x kao i x+ ++x daju rezultat 3
[ Shadowed @ 19.01.2018. 23:55 ] @
Iz toga sto si napisao bi se dalo zakljuciti da inkrement x++ inkrement ima prednost u odnosu na sabiranje pa je x+++x zapravo (x++)+x. Iz tog razloga 1+++x ne prolazi jer je to (1++)+x a 1++ ne moze da se izvrsi.
Isto ponasanje je i u C# / Visual Studio. x+++x moze, x+++1 ne. Takodje, x+++x je automatski formatirao (dodao space-ove) i napravio x++ + x.
[ Everbeck @ 20.01.2018. 00:04 ] @
Ne verujem da se Eclipse tu nešto pita. Javac ne dozvoljava inkrementiranje literala.
[ Nedeljko @ 20.01.2018. 07:21 ] @
Ovo je C ekvivalent:

Code (c):

#include <stdio.h>

int plus(int x, int y)
{
     return x+y;
}

int inc(int *x)
{
     ++*x;

     return *x;
}

int main()
{
     int x = 1;
     printf("%d\n", plus(x, inc(&x)));
   
     return 0;
}
 


inc mora da se izvrši pre plus jer je rezultat od inc operand za plus. Međutim, redosled izračunavanja operanada od plus (prvo prvi, pa drugi ili prvo drugi, pa prvi) je nedefinsan. Prepušta se kompajleru da postupi kako hoće u cilju optimizacije. Kada na GNU/Linux sistemu kompajliram GNU-ovim gcc-om, dobija se 4, a kad kompajliram Apple-ovim clang-om, dobijam 3.
[ Nedeljko @ 20.01.2018. 07:24 ] @
Kada x + ++x kompajliram clang-om, dobijam upozorenje "unsequenced modification and access to 'x' [-Wunsequenced]".
[ Branimir Maksimovic @ 20.01.2018. 08:32 ] @
Citat:
Nedeljko:
Ovo je C ekvivalent:

Code (c):

#include <stdio.h>

int plus(int x, int y)
{
     return x+y;
}

int inc(int *x)
{
     ++*x;

     return *x;
}

int main()
{
     int x = 1;
     printf("%d\n", plus(x, inc(&x)));
   
     return 0;
}
 


inc mora da se izvrši pre plus jer je rezultat od inc operand za plus. Međutim, redosled izračunavanja operanada od plus (prvo prvi, pa drugi ili prvo drugi, pa prvi) je nedefinsan. Prepušta se kompajleru da postupi kako hoće u cilju optimizacije. Kada na GNU/Linux sistemu kompajliram GNU-ovim gcc-om, dobija se 4, a kad kompajliram Apple-ovim clang-om, dobijam 3.


Pa vidi ovo nije nimalo isto kao osnovni primer, zato sto je u prethodnom slucaju undefined, a ovo tvoje unspecified ;)
Razlika je u tome sto kod undefined, kompajler moze da uradi bilo sta (recimo lansira raketu), a kod unspecified mora da da rezultat ali koji nije specificiran ;p

[ Nedeljko @ 20.01.2018. 09:33 ] @
Zamenio sam prefiksno inkrementiranje unarnom funkcijom i sabiranje unarnom funkcijom da se lepše vidi.
[ Nedeljko @ 20.01.2018. 14:37 ] @
U čemu smatraš da je tačno razlika?
[ Branimir Maksimovic @ 20.01.2018. 17:26 ] @
Pa funkcija izmedju parametara ima sequence point ali je redosled evaluacije parametara unspecified, dok operatori nemaju seqence point, pa se istovremeno vadi i menja vrednost x sto je undefined behavior.

edit: naravno ovo se odnosi na C i C++, ne na druge jezike.

[Ovu poruku je menjao Branimir Maksimovic dana 20.01.2018. u 18:45 GMT+1]
[ Nedeljko @ 20.01.2018. 18:52 ] @
Možeš li to da dokumentuješ?
[ Nedeljko @ 20.01.2018. 18:57 ] @
Drvo izračunavanja je sledeće:

Code:

plus --+ x
       |
       + inc --- & --- x


redosled izvršavanja grana je nedefinisan. Isto važi i za operatore.
[ Branimir Maksimovic @ 20.01.2018. 19:05 ] @
Citat:
Nedeljko:
Možeš li to da dokumentuješ?


Opste poznata stvar...
[ Branimir Maksimovic @ 20.01.2018. 19:20 ] @
Citat:
Nedeljko:
Drvo izračunavanja je sledeće:

Code:

plus --+ x
       |
       + inc --- & --- x


redosled izvršavanja grana je nedefinisan. Isto važi i za operatore.


Nije nedefinisan nego nespecificiran. Kazem postoji velika razlika u nedefinisanom i nespecificiranom ponasanju u kompajlera kod C i C++.
Pitanje je jedino jel ovo tvoje unspecified ili undefined. Tu nisam siguran posto nisam pogledao u citap.
[ Branimir Maksimovic @ 20.01.2018. 19:38 ] @
I ne bih lenj da proverim:

Code:

~/.../bmaxa_data/examples >>> g++ -Wall interv.c                                                                                                                                                         
interv.c: In function ‘int main()’:
interv.c:11:25: warning: operation on ‘x’ may be undefined [-Wsequence-point]
     printf("%d\n",add(x,++x));
                         ^~~
~/.../bmaxa_data/examples >>> cat interv.c                                                                                                                                                               
#include <stdio.h>
int add(int a,int b){
    return a+b;
}
int& inc(int& x){
    return ++x;
}
int main(void) {
    int x = 1;
    printf("%d\n",add(x,inc(x)));
    printf("%d\n",add(x,++x));
}



Znaci samo u slucaju da direktno inkrementiras u parameter listi je undefined, a u tvom slucaju, posto zoves inc, to je unspecified
zato sto poziv f-je ubacuje sequence point, a ne zarez u parameter listi kako sam prvo mislio ;)

[ Nedeljko @ 21.01.2018. 13:21 ] @
Undefined behavior - ponšanje može biti u istom stanju mašine različito, odnosno isti program pokrenut više puta sa istim ulazima može imati različito ponešanje i rezultate. Primer: ponašanje zavisi od vrednosti promenljive kojoj prethodno nije dodeljena vrednost, pa je vrednost u principu nasumična (zatečeno stanje u memoriji).

Unspecified behavior - ponašanje nije definisano standardom, pa program kompajliran različitom kompajlerima može imati različito ponašanje. Primer: redosled izračunavanja argumenata funkcije na mestu poziva ili redosled operacija koje se izvršavaju u različitim nitima.
[ Branimir Maksimovic @ 09.05.2018. 04:06 ] @
Code:

main(t,_,a)
char *a;
{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,
main(-86, 0, a+1 )+a)):1,t<_?main(t+1, _, a ):3,main ( -94, -27+t, a
)&&t == 2 ?_<13 ?main ( 2, _+1, "%s %d %d\n" ):9:16:t<0?t<-72?main(_,
t,"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+\
,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/\
+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){n\
l]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#\
n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;\
#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/")
:t<-50?_==*a ?putchar(a[31]):main(-65,_,a+1):main((*a == '/')+t,_,a\
+1 ):0<t?main ( 2, 2 , "%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc \
i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);} 


Pogodite sta ovo daje kao rezultat ;)
Samo moze sa C kompajlerom, C++ ovo ne moze da proguta.
[ Djetvan @ 05.06.2018. 10:14 ] @
Oba rezultata "čini" mi se da su dobra jer razlika je minimalna, samo jedan (1)