Procediamo con ordine:
- Il prototipo di funzione dovrebbe essere qualcosa del genere
bool func(size_t *v, size_t sz, size_t n);
La scelta di ritornare un booleano permette di dare un feedback al chiamante indicando con true che tutto è andato a buon fine e con false che si è verificato un errore. Qui le due condizioni di errore che si possono verificare riguardano il valore del puntatore *v che potrebbe essere NULL, quindi non valido, e la dimensione dell'array che potrebbe non essere sufficiente per contenere tutti i numeri pari richiesti. Chiaramente se il chiamante passa una dimensione non veritiera si possono verificare due problemi:
- la funzione restituisce false anche se l'array era potenzialmente in grado di contenere tutti i numeri pari, nel caso in cui al posto di sz venga passato un valore inferiore alla dimensione reale dell'array. Ma qui è "colpa" del chiamante.
- Segmentation fault su *BSD Linux e "Access violation" su Windows nel caso in cui al posto di sz venga passato un valore che è maggiore della dimensione effettiva dell'array.
In ogni caso quanto esposto sopra va preso con le pinze ed eventualmente rivisto da persone esperte perché potrebbe facilmente una soluzione poco ottimale, essendo anche io agli inizi. Il software engineering è un'arte e di certo non la conosco.
- Suppongo che tu sappia convertire un numero decimale in binario e viceversa e che tu conosca almeno i tre operatori logici universali (NOT, AND, OR). Se prendi carta e penna e provi a convertire alcuni numeri in binario, noterai che i numeri pari hanno LSB a 0 mentre quelli dispari a 1. Facendo l'AND bit a bit tra un numero e la costante 1, si ottiene il bit meno significativo che indica se un numero è pari o no. In C ciò può essere fatto così
numero & 1
- Se provi a convertire qualche numero scelto a caso in binario e a convertire in seguito il doppio, noterai che il doppio del primo numero in binario è uguale al primo con uno zero aggiunto a destra. Si può dire sostanzialmente che tutti bit di un numero vengono traslati di una posizione verso sinistra quando tale numero viene moltiplicato per due. L'operatore shift (<< o >>) sposta di x posizioni i bit di un numero verso sinistra o verso destra. Negli interi unsigned MSB e LSB vengono persi usando l'operatore shift, mentre negli interi segnati tutto dipende dall'implementazione.
4 -> 100
4 << 1 = 1000 = 8
1 >> 4 = 0010 = 2
<< in C, come già detto, è l'operatore left shift e non ha nulla a che vedere con << del C++, di cui non so assolutamente nulla.