• 337 odgovora
  • 167.779 pregleda
Re: Kod koji daje neočekivani rezultat 19.01.2018. u 23:55 · pre 106 meseci #21
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.
Potpis
Nebojsa Milanovic:
-Trumpa smatram vrhunskim predsednikom i voleo bih da živim u državi na čijem je on čelu
-Rusija ne laže, ne vodi osvajačke ratove
-Trump je svetla tačka u USA blatu
-Elon Musk, možda najpametniji i najtrezveniji Amerikanac
Re: Kod koji daje neočekivani rezultat 20.01.2018. u 07:21 · pre 106 meseci #23
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.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Kod koji daje neočekivani rezultat 20.01.2018. u 07:24 · pre 106 meseci #24
Kada x + ++x kompajliram clang-om, dobijam upozorenje "unsequenced modification and access to 'x' [-Wunsequenced]".
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Kod koji daje neočekivani rezultat 20.01.2018. u 08:32 · pre 106 meseci #25
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

Re: Kod koji daje neočekivani rezultat 20.01.2018. u 09:33 · pre 106 meseci #26
Zamenio sam prefiksno inkrementiranje unarnom funkcijom i sabiranje unarnom funkcijom da se lepše vidi.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Kod koji daje neočekivani rezultat 20.01.2018. u 14:37 · pre 106 meseci #27
U čemu smatraš da je tačno razlika?
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Kod koji daje neočekivani rezultat 20.01.2018. u 17:26 · pre 106 meseci #28
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]
Re: Kod koji daje neočekivani rezultat 20.01.2018. u 18:52 · pre 106 meseci #29
Možeš li to da dokumentuješ?
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Kod koji daje neočekivani rezultat 20.01.2018. u 18:57 · pre 106 meseci #30
Drvo izračunavanja je sledeće:

Code:

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


redosled izvršavanja grana je nedefinisan. Isto važi i za operatore.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Kod koji daje neočekivani rezultat 20.01.2018. u 19:20 · pre 106 meseci #32
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.
Re: Kod koji daje neočekivani rezultat 20.01.2018. u 19:38 · pre 106 meseci #33
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 ;)

Re: Kod koji daje neočekivani rezultat 21.01.2018. u 13:21 · pre 106 meseci #34
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.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Kod koji daje neočekivani rezultat 09.05.2018. u 04:06 · pre 102 meseci #35
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.
Re: Kod koji daje neočekivani rezultat 22.12.2019. u 19:03 · pre 83 meseci #38
Kada se karakteri u stringu "9>AEFK" pomere za deset mesta dobijemo karaktere "CHKOPU", što su gle čuda sve karakteri u tvom imenu. Pretpostavljam da će rezultat rada programa biti tvoje ime.

Ali treba da znaš da rand funkcija nije standardizovana. Razni kompajleri proizvode različite rezultate za isti početni seed. Čak i isti kompajleri u različitim verzijama mogu da proizvedu različit rezultat. Zato, ono što funkcioniše kod tebe ne mora da funkcioniše kod nekog drugog.
Re: Kod koji daje neočekivani rezultat 22.12.2019. u 21:03 · pre 83 meseci #39
On to vrlo dobro zna, ali je zajebant. Pored ostalog, gcc mu izbacuje upozorenja

$ echo "main(){for(srand(-67303081);putchar(10+\"9>AEFK\"[7&rand()])>11;);}" > c.c
$ gcc c.c
c.c:1:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main(){for(srand(-67303081);putchar(10+"9>AEFK"[7&rand()])>11;);}
^~~~
c.c: In function ‘main’:
c.c:1:12: warning: implicit declaration of function ‘srand’ [-Wimplicit-function-declaration]
main(){for(srand(-67303081);putchar(10+"9>AEFK"[7&rand()])>11;);}
^~~~~
c.c:1:29: warning: implicit declaration of function ‘putchar’ [-Wimplicit-function-declaration]
main(){for(srand(-67303081);putchar(10+"9>AEFK"[7&rand()])>11;);}
^~~~~~~
c.c:1:51: warning: implicit declaration of function ‘rand’ [-Wimplicit-function-declaration]
main(){for(srand(-67303081);putchar(10+"9>AEFK"[7&rand()])>11;);}



[Ovu poruku je menjao Nedeljko dana 22.12.2019. u 22:14 GMT+1]
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Kod koji daje neočekivani rezultat 23.12.2019. u 19:55 · pre 83 meseci #40
Ono sto je neocekivano u tom kodu je sto ljudi ne razlikuju teoriju od prakse. Naime, u teorijiu izmedju teorije i prakse nema razlike, ali u praksi i te kako ime.

Ajde da se malo poigramo sa nekim cudom kompajliranim kodom. Uradimo listu simbola tako kompajliranog programa.

Code:

[chupcko@main] 1 /home/chupcko > nm a
0000000000600e50 d _DYNAMIC
0000000000601000 d _GLOBAL_OFFSET_TABLE_
0000000000400818 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
0000000000600e30 d __CTOR_END__
0000000000600e28 d __CTOR_LIST__
0000000000600e40 D __DTOR_END__
0000000000600e38 d __DTOR_LIST__
0000000000400948 r __FRAME_END__
0000000000400824 r __GNU_EH_FRAME_HDR
0000000000600e48 d __JCR_END__
0000000000600e48 d __JCR_LIST__
0000000000601048 D __TMC_END__
0000000000601048 B __bss_start
0000000000601038 D __data_start
00000000004007d0 t __do_global_ctors_aux
0000000000400660 t __do_global_dtors_aux
0000000000601040 D __dso_handle
                 w __gmon_start__
0000000000600e28 d __init_array_end
0000000000600e28 d __init_array_start
00000000004007c0 T __libc_csu_fini
0000000000400750 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000601048 D _edata
0000000000601058 B _end
0000000000400808 T _fini
0000000000400510 T _init
00000000004005a0 T _start
0000000000601048 b completed.6955
0000000000601038 W data_start
00000000004005d0 t deregister_tm_clones
0000000000601050 b dtor_idx.6957
00000000004006d0 t frame_dummy
0000000000400700 T main
                 U putchar@@GLIBC_2.2.5
                 U rand@@GLIBC_2.2.5
0000000000400610 t register_tm_clones
                 U srand@@GLIBC_2.2.5


Sta mozemo videti, da je gomila funkcija definisano, ali ne i rand i srand. Koja naime pripadaju glibc-u. Dakle mozemo slobodno da tvrdimo da rand nije deo jezika nego standardne biblioteke. Samim tim cime god da kompajliras i ako ne menjas standardnu biblioteku davace isti kod.

A ako odemo jos korak dalje i vidimo da li je stdlib po POSIX.1-2001. A da kazemo da nema smisla ako nije :)))), onda cemo videti da se uvek isto implementira rand i srand.

Sve u svemu jos jedna neocekivana stvar je da ce na skoro svim linuxima, androidima, openwrtovima da da isti rezultat :). E sada i to mi je dovoljno :)))). Sve u svemu kod daje neocekivan rezultat, na prvu loptu, a kada razmislis shvatis da radi :)))).

Sve u svemu, jesam zajebant i znam da skolnim upozorenja, ali eto volem da imam u jednom redu potpis :).

P.S. Ideja je originalno moja. a program je sladak, pricali vi sta hocete :))))).

Code:

   /**/main(e,c,h,o,_){e?(main(0,1,0,0,/**/
  /**/3),puts("")):_--&&(main(e,c<<_,h/**/
 /**/+3,o,_),putchar(223&2+"nimfs_a"[/**/
/**/(c&2)+h+o]),main(e,c,h,o+1,_));}/**/
Potpis
CHUPCKO
Odgovori
Prijavite se da biste odgovorili u ovoj temi.PrijavaRegistracija

Premeštanje teme