Preparazione ai CyberChallenge

Da dove posso partire per risolvere il seguente problema??

Consider the following code fragment:
unsigned BB[] = ???;
printf("%s\n", (char *) (BB + 1));
Assumptions:
- 32-bit little-endian platform
- sizeof(char) == 1
- sizeof(unsigned) == 4
How would you initialize (i.e., replace ??? above) BB so as to get the
output “Say my name”?
A. {0xA5207961, 0x536E2079, 0x6D656D61, 0x0}
B. {0xA5, 0x53617920, 0x6D79206E, 0x616D6500}
C. {0xA5536179, 0x206D7920, 0x6E616D65, 0x0}
D. {0xA5, 0x20796153, 0x6E20796D, 0x656D61}
Just recall that the decimal ASCII code of the space is 32.
1 Mi Piace

Parto dal fatto che non sono sicuro di alcuni passaggi, ma ti esprimo il mio ragionamento:
Allora BB+1 equivale a scrivere *(BB[1]). Quindi é l’array dal primo elemento in poi.
Viene poi castatato in un array di char. Ogni char come c’è scritto occupa 1 byte mentre un unsigned ne occupa 4. In notazione esadecimale poi un byte é indicato da una coppia di cifre (16^2 = 2^8).
La stringa é formata da 11 caratteri fondamentalmente diversi tra loro; questo porta ad escludere la risposta A e la risposta C in quanto concludono con una serie di 4 byte tutti equivalenti a 0 (quel 0x0) lasciando quindi solo 8 byte notevoli. Le risposte B e Di hanno invece 12 byte notevoli, uno in più della lunghezza della stringa; per capire questo concetto basta sapere che alla fine di un array di caratteri il C (in quanto non ha nessun modo di sapere la dimensione, ma supporta la stampa) prevede l’uso di un carattere terminatore ‘\0’ non visibile poi. Ora se devo sparare a caso questo carattere equivarrà a un numero notevole piuttosto che a uno qualsiasi; la mia risposta é quindi la B che come byte finale ha 0.
Altro modo per risolverlo é sfruttare l’informazione che lo spazio in decimale é 32, convertito in esadecimale vale 0x20 e controlli in quale risposta compare nei punti giusti (la B). Oppure se hai una tabella ASCII sottomano vedi subito che il carattere ‘S’ equivale a 0x53 e l’unica risposta che inizia così é la B

Spero mi son fatto capire almeno un pochino:sweat_smile:

1 Mi Piace

Ho fatto un ragionamento simile anche io, arrivando alla stessa risposta, ed infine ho utilizzato il compilatore per controllare.
Con la risposta b, l’output è il seguente:

yaSn ym

L’output corretto invece si ottiene con la risposta d.

L’ho scoperto facendo un paio di prove. La soluzione a questo problema sta nel fatto che la stampa di un valore unsigned (avendo fatto il casting in char) avviene effettivamente al contrario. Se ci fate caso la risposta B potrebbe sembrare corretta in apparenza (come spiegato da @jkm99zambo) ma effettivamente non lo è. Difatti, come ho accennato precedentemente, la stampa viene invertita. Perciò quello che sarebbe la parola “Say” viene tradotta in 0x20(’ ', cioè lo spazio) 79 (‘y’) 61 (‘a’) 53 (‘S’) e non 0x53617920.

Ok, non avevo idea che i 4 byte venissero invertiti

I byte vengono invertiti perchè l’architettura del problema è “little endian”, ovvero salva in memoria valori che occupano più di un byte a partire dal meno significativo.
Quindi, ad esempio, il valore 0xCAFEBABE Viene scritto in memoria come la sequenza di byte BE BA FE CA. Se sembra strano, sappiate che se state scrivendo da un computer questo è quasi sicuramente little endian.
Linko la pagina wikipedia per chi volesse approfondire

2 Mi Piace

Ok, grazie; ora so qualcosa in più