C uganka

Vse o programiranju na in za PC

Moderatorji: Kroko, tilz0R

C uganka

OdgovorNapisal/-a Kroko » 27 Sep 2016, 21:13

Koda: Izberi vse
a = b = c = 1;
c = ++a||++b&&++c;


a = ?
b = ?
c = ?
http://www.planet-cnc.com poskakuješ na eni nogi in žvižgaš alpske podoknice Kroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 4773
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 680 krat
Prejel zahvalo: 1652 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a Dorijan » 27 Sep 2016, 21:33

Koda: Izberi vse
#include <stdio.h>
int a, b,c;

int main()
{
    a = b = c = 1;
    c = ++a||++b&&++c;
   
    char str[10];
    sprintf(str, "%d%d%d", a, b, c);
    printf(str);

    return 0;
}

2, 1, 1 - ne vprašaj zakaj in če je prav ker ne vem. Tako je prvi online compiler mi ven vrgel :)
Dorijan
 
Prispevkov: 715
Pridružen: 21 Jan 2015, 00:09
Zahvalil se je: 3 krat
Prejel zahvalo: 119 krat
Uporabnika povabil: gumby
Število neizkoriščenih povabil: 22

Re: C uganka

OdgovorNapisal/-a Kroko » 27 Sep 2016, 21:36

Vseeno želim še razlago.
http://www.planet-cnc.com poskakuješ na eni nogi in žvižgaš alpske podoknice Kroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 4773
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 680 krat
Prejel zahvalo: 1652 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a sundancer » 27 Sep 2016, 22:04

Haha, dobra!
torej imamo

c = izjava1 || ( izjava2 && izjava3 )

izjava1 = ++a .. ta del se izvede, zato a dobi vrednost 2

( izjava2 && izjava3 ) je DRUGI del sestavljene izjave in se sploh ne izvede, ker je PRVI del (izjava1) ze resnicen torej ni potrebe po izvajanju

++b in ++c se torej ne izvede, zato sta b in c se vedno 1

vendar

c = ++a || whatever
in ker izraz ++a dobi vrednost 2 se cju priredi vrednost 2

torej c=2

Kroko se bo strinjal, ostalim pa ne vem ce bo jasno :)
Dyslexic man walks into a bra.
Uporabniški avatar
sundancer
 
Prispevkov: 596
Pridružen: 16 Jan 2015, 23:36
Kraj: Domžale
Zahvalil se je: 217 krat
Prejel zahvalo: 327 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 43

Re: C uganka

OdgovorNapisal/-a sundancer » 27 Sep 2016, 22:09

Razlozil bi lahko tudi na psevdo primeru:

if ( False || True || False || False || False || False ) { nekaj; }

if stavek bo preverjal resnicnost izraza toliko casa dokler ne naleti na en sam samcat True, zato ker je to vse kar ga zanima... namrec za prvim True je lahko se neskocno True ali False vendar to sploh ni vec pomembno ker so operatorji tipa OR
Dyslexic man walks into a bra.
Uporabniški avatar
sundancer
 
Prispevkov: 596
Pridružen: 16 Jan 2015, 23:36
Kraj: Domžale
Zahvalil se je: 217 krat
Prejel zahvalo: 327 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 43

Re: C uganka

OdgovorNapisal/-a Kroko » 28 Sep 2016, 01:03

Kroko se bo strinjal

Kroko se ne strinja. 2, 1, 2 ni pravi odgovor.
http://www.planet-cnc.com poskakuješ na eni nogi in žvižgaš alpske podoknice Kroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 4773
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 680 krat
Prejel zahvalo: 1652 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a VolkD » 28 Sep 2016, 01:28

Koda: Izberi vse
    a = b = c = 1;          // 1 ->  a
                            // 1 ->  b
                            // 1 ->  c   
    c = ++a||++b&&++c;      // a+1 -> a        ; izvaja se z leve proti desni
                            // c= 2 || karkoli ; sledi  1 ->c ;
                            // c ima rezultat zato nadaljnje izvajane bi potrebno členov ni potrebno     


V bistvu je tole neke vrste prikriti if ukaz. Me je nekaj podobnega stalo cel vikend časa, preden sem dojel kaj se je zgodilo.
Zdaj raje bežim od tega, ker je vedno težko razumljivo.
Dokler bodo ljudje mislili, da živali ne čutijo bolečine, bodo živali čutile, da ljudje ne mislijowww.S5tech.net
Uporabniški avatar
VolkD
Administratorji strani
 
Prispevkov: 41597
Pridružen: 29 Dec 2014, 20:49
Kraj: Kačiče (Divača)
Zahvalil se je: 9015 krat
Prejel zahvalo: 5132 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a rafaellsi » 28 Sep 2016, 03:41

Takole bi mogoče jaz še razumel:
Koda: Izberi vse
int a, b, c;
a=b=c=1;
a++;
if (a != 0) {
  c=1;
}
else {
  b++;
  c++;
  if (b != 0 && c != 0) {
   c=1
  }   
  else {
    c=0;
  }
}
rafaellsi
 
Prispevkov: 389
Pridružen: 19 Jan 2015, 01:44
Kraj: Gorenjska
Zahvalil se je: 18 krat
Prejel zahvalo: 38 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 41

Re: C uganka

OdgovorNapisal/-a sundancer » 28 Sep 2016, 05:36

sundancer je napisal/-a:Haha, dobra!
torej imamo

c = izjava1 || ( izjava2 && izjava3 )

izjava1 = ++a .. ta del se izvede, zato a dobi vrednost 2

( izjava2 && izjava3 ) je DRUGI del sestavljene izjave in se sploh ne izvede, ker je PRVI del (izjava1) ze resnicen torej ni potrebe po izvajanju

++b in ++c se torej ne izvede, zato sta b in c se vedno 1

vendar

c = ++a || whatever
in ker izraz ++a dobi vrednost 2 se cju priredi vrednost 2

torej c=2

Kroko se bo strinjal, ostalim pa ne vem ce bo jasno :)


Popravek:
c dobi vrednost 1, ker je celotna izjava True

torej
a=2, ker se ++a izvede
b=1, ker se ++b ne izvede
c=1, ker je celotna izjava pravilna in je True
Dyslexic man walks into a bra.
Uporabniški avatar
sundancer
 
Prispevkov: 596
Pridružen: 16 Jan 2015, 23:36
Kraj: Domžale
Zahvalil se je: 217 krat
Prejel zahvalo: 327 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 43

Re: C uganka

OdgovorNapisal/-a tilz0R » 28 Sep 2016, 07:53

Preprosto, izvede se samo stavek ++a.

Ker je true, se nadaljevanje ne izvaja in spremenljivka dobi vrednost tega inline "if" stavka.

Torej rezultati so 2,1,1. Je pa ++a najprej povečanje, potem branje, tako da gre iz 1 na 2 preden se zapiše v a. Ostala dva sta nespremenjena.

Lep dan še naprej, tokrat se bo Kroko moral strinjat ;)
Knowledge sharing is people' caring., T. MAJERLE
Uporabniški avatar
tilz0R
 
Prispevkov: 1815
Pridružen: 18 Jan 2015, 00:12
Kraj: Črnomelj
Zahvalil se je: 229 krat
Prejel zahvalo: 509 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a forest70 » 28 Sep 2016, 08:33

Kot zanimivost:
Sem Krokotovo kodo potaknil PHP-ju in rezultat je: 211
Koda: Izberi vse
<?php
$a = $b = $c = 1;
$c = ++$a||++$b&&++$c;
echo "\n";
echo  $a . $b .  $c . "\n";
?>
If you pay in bananas, you got monkeys.
Uporabniški avatar
forest70
 
Prispevkov: 2155
Pridružen: 14 Jan 2015, 01:11
Kraj: Koper
Zahvalil se je: 411 krat
Prejel zahvalo: 457 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 122

Re: C uganka

OdgovorNapisal/-a Kroko » 28 Sep 2016, 08:42

Tokrat se strinjam :-)
V c-ju se da napisati zelo kriptično kodo. Vendar je naloga programerja, da piše kodo, ki je lahko razumljiva in jezik sam ni kriv.

Sem pa razmišljal:
"!!" se pogosto uporablja, ko želimo iz neke vrednosti dobiti samo 0 ali 1. Na primer:
Koda: Izberi vse
int a, c;
a = 123;
c = !!a;

!! sta dva operatorja. Ali bi bil tole ekvivalent z enim operatorjem:
Koda: Izberi vse
int a, c;
a = 123;
c = a || 0;

Bi lahko kdo pogledal, v kaj se ta dva primera prevedeta?
http://www.planet-cnc.com poskakuješ na eni nogi in žvižgaš alpske podoknice Kroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 4773
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 680 krat
Prejel zahvalo: 1652 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a tilz0R » 28 Sep 2016, 08:53

Visual Studio prevede oba primera v C = 1;

Zakaj je tako torej, nevem. Tvoja uganka pa naredi, to kar sem povedal, tako da bi za spodnji primer 123 || 0 pričakoval, da bo c = 123, ampak je 1.

Koda: Izberi vse
   int a = 123;
   int c1, c2;

   c1 = a || 0;
   c2 = !!a;

   printf("c1: %d; c2: %d\n", c1, c2);


izpiše: c1: 1; c2: 1
Knowledge sharing is people' caring., T. MAJERLE
Uporabniški avatar
tilz0R
 
Prispevkov: 1815
Pridružen: 18 Jan 2015, 00:12
Kraj: Črnomelj
Zahvalil se je: 229 krat
Prejel zahvalo: 509 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a gumby » 28 Sep 2016, 09:03

|| pomeni logično operacijo (ne bitno), torej naj bi bil rezultat 0 ali 1.
Sicer pa mene tudi zanima, v kaj se prevedeta oba primera...
my brain hurts
Uporabniški avatar
gumby
 
Prispevkov: 2573
Pridružen: 14 Jan 2015, 19:49
Kraj: Lendava
Zahvalil se je: 108 krat
Prejel zahvalo: 604 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 63

Re: C uganka

OdgovorNapisal/-a tilz0R » 28 Sep 2016, 09:05

gumby je napisal/-a:|| pomeni logično operacijo (ne bitno), torej naj bi bil rezultat 0 ali 1.
Sicer pa mene tudi zanima, v kaj se prevedeta oba primera...


Imaš zgoraj en post.

Prva ugabka se prevede v 2,1,1
Knowledge sharing is people' caring., T. MAJERLE
Uporabniški avatar
tilz0R
 
Prispevkov: 1815
Pridružen: 18 Jan 2015, 00:12
Kraj: Črnomelj
Zahvalil se je: 229 krat
Prejel zahvalo: 509 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a S53DZ » 28 Sep 2016, 09:28

Mene pa zanima, čemu bi delal logični or na spremenljivki, ki ni normalizirana?
Če se pri tem testira samo, če je nič ali ne.

Kot je rekel gumby: logični || in bitni |.

Sicer pa, za pogledati asemblersko kodo prevedene C kode, moraš imeti gdb s tui opcijo. Jaz je žal nimam.
http://stackoverflow.com/questions/1902 ... ion-in-gdb

LP Bojan
Zadnjič spremenil S53DZ, dne 28 Sep 2016, 09:37, skupaj popravljeno 1 krat.
Uporabniški avatar
S53DZ
 
Prispevkov: 1164
Pridružen: 18 Jan 2015, 10:58
Kraj: Ljubljana
Zahvalil se je: 204 krat
Prejel zahvalo: 392 krat
Uporabnika povabil: S52O
Število neizkoriščenih povabil: 42

Re: C uganka

OdgovorNapisal/-a Kroko » 28 Sep 2016, 09:30

@tilz0r - v gumbijem naju zanima, v kaj se prevede (asembler) in ne kako se izvede.
http://www.planet-cnc.com poskakuješ na eni nogi in žvižgaš alpske podoknice Kroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 4773
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 680 krat
Prejel zahvalo: 1652 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a booxco » 28 Sep 2016, 09:42

Trenutno veljaven in najbolj uporabljan standard za jezik C, med drugim pravi:

6.5.14 Logical OR operator
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.
If the first operand compares unequal to 0, the second operand is not evaluated.


Vsi prevajalniki, ki se držijo tega standarda (in gcc se), morajo pri tej uganki vrniti enak rezultat.
booxco
 
Prispevkov: 113
Pridružen: 25 Sep 2016, 22:17
Zahvalil se je: 18 krat
Prejel zahvalo: 47 krat
Uporabnika povabil: radix
Število neizkoriščenih povabil: 9

Re: C uganka

OdgovorNapisal/-a tilz0R » 28 Sep 2016, 09:43

@Kroko in @gumby

Ne vem, če vama je to ok ampak disasembly visual studia je sledeč:

Koda: Izberi vse
int main() {
00F94E00  push        ebp 
00F94E01  mov         ebp,esp 
00F94E03  sub         esp,0E8h 
00F94E09  push        ebx 
00F94E0A  push        esi 
00F94E0B  push        edi 
00F94E0C  lea         edi,[ebp-0E8h] 
00F94E12  mov         ecx,3Ah 
00F94E17  mov         eax,0CCCCCCCCh 
00F94E1C  rep stos    dword ptr es:[edi] 
   
   int a = 123;
00F94E1E  mov         dword ptr [a],7Bh 
   int c1, c2;


   c1 = a || 0;
00F94E25  cmp         dword ptr [a],0 
00F94E29  jne         main+3Bh (0F94E3Bh) 
00F94E2B  xor         eax,eax 
00F94E2D  jne         main+3Bh (0F94E3Bh) 
00F94E2F  mov         dword ptr [ebp-0E8h],0 
00F94E39  jmp         main+45h (0F94E45h) 
00F94E3B  mov         dword ptr [ebp-0E8h],1 
00F94E45  mov         ecx,dword ptr [ebp-0E8h] 
00F94E4B  mov         dword ptr [c1],ecx 
   c2 = !!a;
00F94E4E  cmp         dword ptr [a],0 
00F94E52  je          main+60h (0F94E60h) 
00F94E54  mov         dword ptr [ebp-0E8h],1 
00F94E5E  jmp         main+6Ah (0F94E6Ah) 
00F94E60  mov         dword ptr [ebp-0E8h],0 
00F94E6A  mov         eax,dword ptr [ebp-0E8h] 
00F94E70  mov         dword ptr [c2],eax 

   printf("c1: %d; c2: %d\n", c1, c2);
00F94E73  mov         eax,dword ptr [c2] 
00F94E76  push        eax 
00F94E77  mov         ecx,dword ptr [c1] 
00F94E7A  push        ecx 
00F94E7B  push        0F96CF8h 
00F94E80  call        _printf (0F91325h) 
00F94E85  add         esp,0Ch 
   
   return 0;
00F94E88  xor         eax,eax 
}
Knowledge sharing is people' caring., T. MAJERLE
Uporabniški avatar
tilz0R
 
Prispevkov: 1815
Pridružen: 18 Jan 2015, 00:12
Kraj: Črnomelj
Zahvalil se je: 229 krat
Prejel zahvalo: 509 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a Kroko » 28 Sep 2016, 09:45

Izgleda, da je !! "cenejši". Hvala tilz0r.

S53DZ je napisal/-a:Mene pa zanima, čemu bi delal logični or na spremenljivki, ki ni normalizirana?


Če sprašuješ zaradi mojega !! vprašanja - zato, ker potrebuješ samo vrednosti 0, 1 kadar nastavljaš bite.

Če pa sprašuješ zaradi prvega primera - ni pametnega razloga.
http://www.planet-cnc.com poskakuješ na eni nogi in žvižgaš alpske podoknice Kroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 4773
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 680 krat
Prejel zahvalo: 1652 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a tilz0R » 28 Sep 2016, 09:50

Aia, sej pa prvi prvi primer je jasen zakaj je 2, 1, 1.

Vsaka || operacija ima 1 ali 0 rezultat, ne glede na vrednosti.

ker je ++a bil 2, je bil || automatsko true, kar pomeni 1, in to se je shranlo v c spremenljivko, a se je povečala za 1 (nova vrednost = 2), b ostane nespremenjen.

Mislim, da na tej točki lahko zaključimo ;)
Knowledge sharing is people' caring., T. MAJERLE
Uporabniški avatar
tilz0R
 
Prispevkov: 1815
Pridružen: 18 Jan 2015, 00:12
Kraj: Črnomelj
Zahvalil se je: 229 krat
Prejel zahvalo: 509 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a VolkD » 28 Sep 2016, 09:58

Kroko je napisal/-a:@tilz0r - v gumbijem naju zanima, v kaj se prevede (asembler) in ne kako se izvede.
To je pa verjetno odvisno od tega za kateri ciljni procesor prevajaš. In seveda tudi od tega s katerim prevajalnikom prevajaš.
Dokler bodo ljudje mislili, da živali ne čutijo bolečine, bodo živali čutile, da ljudje ne mislijowww.S5tech.net
Uporabniški avatar
VolkD
Administratorji strani
 
Prispevkov: 41597
Pridružen: 29 Dec 2014, 20:49
Kraj: Kačiče (Divača)
Zahvalil se je: 9015 krat
Prejel zahvalo: 5132 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C uganka

OdgovorNapisal/-a booxco » 28 Sep 2016, 10:05

VolkD je napisal/-a:
Kroko je napisal/-a:@tilz0r - v gumbijem naju zanima, v kaj se prevede (asembler) in ne kako se izvede.
To je pa verjetno odvisno od tega za kateri ciljni procesor prevajaš. In seveda tudi od tega s katerim prevajalnikom prevajaš.


Ja, odvisno je od platforme in pameti prevajalnika. Logika pa mora biti taka, kot smo že ugotovili, in sicer zato, ker tako zapoveduje standard.

Na primer, online C to assembler, https://assembly.ynh.io/, gcc vsako od treh vrstic:

Koda: Izberi vse
 c1 = a || 0;
 c1 = !!a;
 c1 = a != 0;


prevede enako v

Koda: Izberi vse
000f 837DF400       cmpl   $0, -12(%rbp)
0013 0F95C0         setne   %al
0016 0FB6C0         movzbl   %al, %eax
0019 8945F8         movl   %eax, -8(%rbp)


torej je kar se tiče hitrosti vseeno, katero od teh treh sintaks uporabimo. Tu je odločitev programerja, kaj se mu zdi bolj razumljivo.
booxco
 
Prispevkov: 113
Pridružen: 25 Sep 2016, 22:17
Zahvalil se je: 18 krat
Prejel zahvalo: 47 krat
Uporabnika povabil: radix
Število neizkoriščenih povabil: 9

Re: C uganka

OdgovorNapisal/-a gumby » 28 Sep 2016, 15:22

AVR-GCC naredi povsem enako kodo v obeh primerih:
Koda: Izberi vse
   x=a||0;
 97c:   90 91 ef 01    lds   r25, 0x01EF
 980:   81 e0          ldi   r24, 0x01   ; 1
 982:   91 11          cpse   r25, r1
 984:   01 c0          rjmp   .+2         ; 0x988
 986:   80 e0          ldi   r24, 0x00   ; 0
 988:   89 83          std   Y+1, r24   ; 0x01

   x=!!a;
 98a:   90 91 ef 01    lds   r25, 0x01EF
 98e:   81 e0          ldi   r24, 0x01   ; 1
 990:   91 11          cpse   r25, r1
 992:   01 c0          rjmp   .+2         ; 0x996
 994:   80 e0          ldi   r24, 0x00   ; 0
 996:   89 83          std   Y+1, r24   ; 0x01
my brain hurts
Uporabniški avatar
gumby
 
Prispevkov: 2573
Pridružen: 14 Jan 2015, 19:49
Kraj: Lendava
Zahvalil se je: 108 krat
Prejel zahvalo: 604 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 63


Vrni se na Programski jeziki

Kdo je na strani

Po forumu brska: 0 registriranih uporabnikov in 2 gostov