Šta je novo?

Kratki C kviz

  • Začetnik teme Začetnik teme ABET
  • Datum pokretanja Datum pokretanja

ABET

Banned
Banovan
Učlanjen(a)
26.03.2007
Poruke
14,009
Poena
720
Video na redditu, besramno kopirao pitanja, kome smeta sto nema izvora nek ne odgovara na pitanja. Da pocnemo:

Pitanje broj 1
Kod:
struct S{
  int i;
  char c;
} s;

main(){
  return sizeof(*(&s));
}
Vracena vrednost je ___?

Pitanje broj 2
Kod:
main(){
  char a = 0;
  short int b = 0;
  return sizeof(b) == sizeof(a+b);
}
Vracena vrednost je ___?

Pitanje broj 3
Kod:
main(){
  char a = ‘ ‘ * 13;
  return a;
}
Vracena vrednost je ___?

Pitanje broj 4
Kod:
main()
{
  int i = 16;
  return (((((i >= i) << i) >> i) <= i));
}
Vracena vrednost je ___?

Pitanje broj 5
Kod:
main(){
  int i = 0;
  return i++ + ++i;
}
Vracena vrednost je ___?

...

Na kraju, posto nisam ponudio moguce odgovore da birate koji od njih je tacan, red je da ostavim malu pomoc. Preporucuje se da ne aktivirate spojler, posto nije bas tako mala pomoc u pitanju zavisno kako je skapirate.
Hint: u pitanju je test koji vise testira licnost programera nego njegovo znanje 😉
 
1. Zavisi od switcheva za optimizaciju, može biti 5 ili 8.
2. 0
3. Ima li razmaka između ''? Ako ima onda je -32.
4. 1
5. 1

Sent from my Nexus 6P using Tapatalk
 
Izgleda da je forumasima ovo glupo. Jeste u neku ruku, ali nije bas bez poente. Ako ima vremena, volje i zelje ne bi bilo lose da jedini koji odgovorio na pitanja (@yooyo) objasni kako je dosao do rezultata. Mozda to ozivi diskusiju.

Pitanje broj 3: razmaka ima, sto moze lako da se proveri.
 
1. Procesori vole podatke na "okruglim" adresama, odnosno na adresama koje su deljive sa 4. To je zbog bržeg prebacivanja iz memorije u keš i registre. Da bi program radio efikasnije, kompajler će sve elemente strukture postaviti na adrese deljive sa 4 a i sama veličina strukture će biti deljiva sa 4. U ovom slučaju int je 4 bajta, char je 1. Bez optimizacije je 4+1, sa optimizacijom je 4+4.

2. Veličina char je 1 bajt, short int je 2 bajta, ali ovo je trik pitanje, koje se svodi na da li je veličina short int (koja je 2) jednaka veličini za zbira a i b (0 u ovom slučaju) ali je veličina zbira zapisana kao int te je sizeof(a+b) u stvari sizeof(0) odnosno sizeof(int) a to je 4. 2 nije jednako 4 te je rezultat netačan pa je vraćena vrednost 0.

3. char je tip koji zauzima 1 bajt (8 bita) i koji koristi poslednji bit kao znak. Opseg koji moze da se smesti u char je od -128 do 127.
' ' (razmak) ima ascii code 32. 32 * 13 = 416 (1 10100000), sto je vise nego sto char moze da primi te se svi bitovi iznad 8-og odbacuju i ostaje samo (10100000) sto je -96. Napravio sam gresku u prvom odgovoru 🙂

4. i = 16. Vodeci racuna o zagradama i redosledu operacija, i >= i (16 >= 16) je true, odnosno 1. Sledeca operacija je shiftovanje u levo 16 puta pa onda shift u desno 16 i opet dobijamo 1. Na kraju da li je 1 <= 16. Resenje je true, odnosno 1.

5. Ovo ima dosta veze sa kompajlerom. U izrazu imamo povecavanje i za jedan na dva mesta. Kada je ++ pre varijable, onda se varijabla povecava za 1 pre upotrebe, a kada je ++ posle varijable, onda se povecava za 1 posle upotrebe. return i++ + ++i bi se moglo tumaciti na sledeci nacin:
- return 0 + 1. Vraca se rezultat 1 a i se povecava za 1 i dobija vrednost 2.
- racuna se sa desna u levo, gde se i prvo poveca pa postane 1 pa se sabere sa i koje vec sad ima vrednost 1. Rezultat je return 1 + 1. Vraca se rezultat 2.

npr:
Kod:
	int i = 0;
	printf("\n%d", i++ + i++ + i++);

	i = 0;
	printf("\n%d", ++i + ++i + ++i);

Sve zavisi kako ce kompajler da obradi izraz.
 
Poslednja izmena:
Izgleda da je forumasima ovo glupo. Jeste u neku ruku, ali nije bas bez poente.

Nije glupo nego svi cepaju javascript i slažu sličice u angularu, zabole ih za structove 😀

5. Ovo ima dosta veze sa kompajlerom. U izrazu imamo povecavanje i za jedan na dva mesta. Kada je ++ pre varijable, onda se varijabla povecava za 1 pre upotrebe, a kada je ++ posle varijable, onda se povecava za 1 posle upotrebe. return i++ + ++i bi se moglo tumaciti na sledeci nacin:
- return 0 + 1. Vraca se rezultat 1 a i se povecava za 1 i dobija vrednost 2.
- racuna se sa desna u levo, gde se i prvo poveca pa postane 1 pa se sabere sa i koje vec sad ima vrednost 1. Rezultat je return 1 + 1. Vraca se rezultat 2.

Ovo sa više operanada u jednoj liniji mi je uvek bilo zanimljivo, u prvoj godini sam se dosta zezao sa tim sa kolegom s PMF-a koji je smišljao neke ludačke izraze. Onda sam se na kraju smorio kad sam skapirao da je to ustvari unspecified i da zavisi od implementacije u kompajleru. U C# su stvari određenije u odnosu na C i C++.

Voleo bih da vidim kako je tačno kompajler preveo i++ + ++i i kako se menjaju vrednosti u registrima. Ne mogu ovako na prvu loptu da skapiram šta tačno radi.

Kod:
    int a = 0;
    int b = 0;
    int c = 0;
    int i = 0;
    int j = 0;
    int k = 0;

    printf("\n%d", ++a + ++a);
	printf("\n%d", ++b + ++b + ++b);
	printf("\n%d", ++b + ++b + ++b + ++b);
	printf("\n%d", i++ + i++);
	printf("\n%d", j++ + j++ + j++);
	printf("\n%d", k++ + k++ + k++ + k++);

    return 0xDEAD;

vraća

Kod:
4
7
23
1
3
6

Npr. kod opcije 5.1, return je kraj sekvence u C-u i svi sporedni efekti moraju da budu završeni pre nego što se funkcija okonča, što znači da će vrednosti i-a biti uvećana za jedan sigurno, ali vrednost koju funkcija vraća ne bi trebalo da zavisi od toga jer je zbir već izračunat pre finalne inkrementacije i.
 
Stvarno sam se nadao da ce neko drugi da uskoci da ne moram ja da se pravim pametan, koji niti sam smislio ova pitanja niti sam neki maher a pogotovo nisam ni blizu @yooyo.

O cemu se ovde radi? Ovo su sve trik pitanja. Kao kada ti pokvareni profesor da zadatak koji ti znas da resis, ali namerno izmeni tekst zadatka i ukljuci odredjene reci zbog kojih tvoje resenje nije tacno. Pa onda kada dodjes na uvid on se pravi pametan kako niko od studenata nije uradio tacno jer ne vode racuna o detaljima. Kada resavas ove zadatke na tvojoj masini, tvoji rezultati su tacni. Medjutim nacin na koji je kviz postavljen to menja jer nije definisana:
- arhitektura procesora (16-bit, 32-bit, 64-bit itd.)
- operativni sistem
- kompajler (visual c++, gcc, clang itd.)
- c standard na koji se dati kompajler oslanja (c89/90, c99, c11 itd.)

Zbog svega toga ti iako mislis da znas koja je najmanja velicina odredjenog tipa podataka, ti to zapravo ne znas. Jer to nigde u zadatku i kodu nije definisano. Niti znas koliki ce padding da doda kompajler da nabaci da bi procesor to efikasnije prebacio u memoriju. Jeste, bice deljivo sa cetiri ali ko kaze da ce to biti najmanji broj koji je veci od vrednosti tipova podataka sa kojima baratas, za koje opet ne znas koliko zauzimaju? Jer ti ne mozes da koristis sizeof(int).

Posto ne znas nista o sistemu koji izvrsava kod jer se podrazumeva da je u pitanju najopstiji moguci slucaj koji zahteva apsolutno portabilan kod koji radi na svim sistemima, kompajlerima, standardima ti uleces u problem posto ovaj kod jednostavno nije takav. Lepo si rekao vise puta, na milost i nemislost si kompajlera. Na jednom sistemu ce da radi kako si rekao, na drugom ce da izbaci nesto drugo, na trecem ce mozda biti problema.

Prva cetiri zadatka su pokrivena barem jednim od C standarda, rezultat zavisi od specificnog sistema na kojem se kod izvrsava. Peti slucaj nije definisan nijednim C standardom, kompajler moze da luduje u tom slucaju i da izbaci kao rezultat sta on hoce.
 
Poslednja izmena:
U pravu si, sve zavisi od kompajlera i arhitekture. Mogao sam samo to da napišem umesto odgovora.

Sent from my Nexus 6P using Tapatalk
 
Kviz koji sam kopirao daje cetiri ponudjena odgovora (pod a, b, c i d) od kojih je d) I don't know. Tacan odgovor na sva pitanja je I don't know 😀

Naravno, autor kviza je medju ponudjene odgovore ubacio i rezultate koje si okacio.

Edit: Poenta ovog kviza, cini mi se, je da ukaze na nedostatke jezika C i jedan je od razloga zasto ga novije generacije izbegavaju osim ako im nije neophodan za rad. Postoje stvari koje nisu striktno definisane, koje prave probleme. Sto znaci da moras potrositi ekstra vreme da namestis da radi tacno onako kako zelis. Kako ide naziv one knjige, C Traps and Pitfalls? Koliko je cuven po jednostavnosti i brzini izvrsavanja koju je moguce postici toliko je ozloglasen jer moze biti zeznut za rad. C++ to podize na novi nivo uvodeci dodatne kompleksnosti.
 
Poslednja izmena:
Za low level stvari c i c++ su nezamenljivi. Uz dodatne direktive, moguće je svaki code naterati da radi identično na bilo kojoj arhitekturi. Ko se bavi tim, zna sve te zamke, npr autori drivera, codeca, protokola,..

Sent from my Nexus 6P using Tapatalk
 
U sustini od svega gore navedenog (OS, kompajler...) je bitan samo standard. Koji standard? Pa bilo koji za koji smo se dogovorili da bude minimalan zahtev za trenutni projekat (Npr. C++03 pa navise). Ljudi koji ozbiljno rade u C/C++ jezicima moraju dosta dobro da poznaju standard (ako zele da pisu portabilan kod) kako se ne bi upucali u nogu. Situacije kao ove gore u pitanjima su pokrivene standardom na jedan od tri nacina: nedefinisano ponasanje, nespecifikovano ponasanje i ponasanje koje je definisano u implementaciji.

Ljudi koji pisu portabilan kod vrlo dobro znaju koje su to situacije i zato ih izbegavaju kad god je to moguce, a moguce je gotovo uvek (tacnije izbegavas kod koji zavisi od implementacije, dok kod koji je nedefinisan jednostavno ne pises, a kod koji je nespecifikovan pises tako da ne zavisis od njegove nespecifikovanosti 😀). U delovima gde nije moguce izbeci kod koji zavisi od implementacije pise se odvojen kod za svaku implementaciju posebno.

Pitanja poput ovih gore sluze samo razonodu, jer svako ko ima iskustva zna da tako napisan kod spada u sivu zonu i niko ga ne bi tako pisao u svakodnevnom poslu. Ali ta pitanja jesu dobar test koliko dobro neko zna standard napamet (sto nije potrebno u svakodnevnom radu, dovoljno je samo da prepoznas sumnjiv kod i da u toj situaciji pogledas sta tacno kaze standard 🙂)
 
Poslednja izmena:
Nazad
Vrh Dno