|
|
|
|
Strumenti |
27-04-2020, 09:25 | #1 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3594
|
C curiosità sui puntatori
se uso una variabile globale del tipo:
char *pippo; e poi la uso in una funzione senza parametri nella quale ne incremento l'indirizzo, quando ritorno al chiamante mi ritrovo con la variabile pippo che punta ad un nuovo indirizzo. Se invece costruisco una funzione dove come parametro passo proprio quel puntatore e lo incremento, al ritorno pippo è come se non si fosse mossa: è normale questo funzionamento? Riassumendo: (attenzione, codice non testato e magari zeppo di errori) Codice:
char *pippo; main() { pluto(); } void pluto() { pippo++; } // ------------------------------------------ char *pippo; int pluto(char *pippo); main() { pluto(pippo); } int pluto(char *pippo) { return pippo++; } Ultima modifica di misterx : 27-04-2020 alle 12:30. |
27-04-2020, 12:57 | #2 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3594
|
risolto ho preso un abbaglio
|
27-04-2020, 21:22 | #3 | |
Member
Iscritto dal: Dec 2006
Messaggi: 33
|
Ciao,
Quote:
Morale della favola: meglio evitare, se possibile, variabili globali ... |
|
28-04-2020, 07:29 | #4 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3594
|
però ho idea di non avere alternative all'uso di una variabile globale per via della storia del passaggio per valore e non per riferimento.
|
28-04-2020, 11:48 | #5 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3594
|
approfitto di questo mia 3d per chiedervi:
se voglio sapere se l'MSB è settato, mi basta nel caso di un byte verificare che il suo valore sia < 128. Tutti quelli maggiori o uguali hanno l'MSB settato a 1, ma perchè molti invece usano questa forma? byte miobyte = 129; byte MSB = (miobyte >> 7) & 1; |
28-04-2020, 18:21 | #6 | ||
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2745
|
Quote:
Esempio: Codice:
main() { char *pippo; //... pippo viene inizializzato in qualche modo pluto(&pippo); //giunti qui pippo è stato incrementato di 1 } int pluto(char **pippo) { (*pippo)++; } Quote:
|
||
28-04-2020, 18:50 | #7 | |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3594
|
Quote:
si, è proprio come nel tuo esempio. Così posso evitare variabili globali che potrebbero creare qualce problema di difficile soluzione. Non aveva mai usato funzioni col doppio asterisco, c'è smpre una prima volta; grazie 1000 |
|
29-04-2020, 08:36 | #8 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3594
|
vi risulta una cosa del genere?
Codice:
char *a; a = (char *) malloc(sizeof(char) * 10); a+=5; free(a); // errore, non viene liberata tutta la memoria |
30-04-2020, 03:28 | #9 |
Senior Member
Iscritto dal: May 2009
Messaggi: 840
|
Il parametro passato a free() deve corrispondere a un indirizzo precedentemente restituito da una malloc(), altrimenti il comportamento della funzione è indefinito, perciò quel codice è effettivamente errato.
|
30-04-2020, 10:36 | #10 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3594
|
grazie per la conferma
|
01-05-2020, 12:51 | #11 | |
Member
Iscritto dal: Feb 2006
Messaggi: 134
|
Quote:
(miobyte & 0x80) Ma ragiono per microcontrollori, dove sprecare operazioni inutili è un delitto |
|
03-05-2020, 09:09 | #12 | |
Senior Member
Iscritto dal: May 2001
Messaggi: 12580
|
Quote:
In ogni caso lì dove entrano in gioco costanti, come nel caso accennato da misterx, è molto probabile che il compilatore ottimizzi già da se quelle operazioni, se le ottimizzazioni sono abilitate (come dovrebbe sempre essere ). Bisognerebbe guardare l'assembly Una precisazione però, bisogna fare attenzione al tipo di dato, il tipo "byte" in C non esiste, parliamo di char o unsigned char. Nel caso di numeri con segno, i bit più significativi possono essere 1 nel caso di numeri negativi in rappresentazione a complemento a 2. In generale per memorizzare i flag infatti è consigliabile usare numeri senza segno. Ultima modifica di WarDuck : 03-05-2020 alle 09:16. Motivo: precisazioni su complemento a 2 |
|
04-05-2020, 14:28 | #13 | ||
Member
Iscritto dal: Feb 2006
Messaggi: 134
|
Quote:
Codice:
unsigned char test1(unsigned char value) { return (value & 0x80); } unsigned char test2(unsigned char value) { return ((value >> 7) & 1); } Codice:
test1: push rbp mov rbp, rsp mov eax, edi mov BYTE PTR [rbp-4], al movzx eax, BYTE PTR [rbp-4] and eax, -128 pop rbp ret test2: push rbp mov rbp, rsp mov eax, edi mov BYTE PTR [rbp-4], al movzx eax, BYTE PTR [rbp-4] shr al, 7 pop rbp ret Resta il fatto che ovviamente anche per me la prima versione è più leggibile Quote:
|
||
05-05-2020, 19:16 | #14 | |
Senior Member
Iscritto dal: May 2001
Messaggi: 12580
|
Quote:
Se uno vuole sapere solo se il bit è settato (quindi è diverso da 0) allora va bene il primo metodo. Tuttavia bisogna stare attenti perché se si fa il confronto chiedendosi se quel test è uguale a 1 ad esempio, chiaramente si sbaglia. La cosa interessante è che usando il trucco di negare doppiamente il valore nella prima funzione (portando i valori tra 0 e 1): Codice:
unsigned char test1(unsigned char value) { return !!(value & 0x80u); } unsigned char test2(unsigned char value) { return ((value >> 7u) & 1u); } Codice:
0000000000000000 <test1>: 0: 89 f8 mov %edi,%eax 2: c0 e8 07 shr $0x7,%al 5: c3 retq 6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) d: 00 00 00 0000000000000010 <test2>: 10: 89 f8 mov %edi,%eax 12: c0 e8 07 shr $0x7,%al 15: c3 retq In tutti gli altri casi, l'AND invece va fatto altrimenti il codice non sarebbe corretto . Se usate unsigned int ad esempio, l'AND compare: Codice:
0000000000000010 <test2>: 10: 89 f8 mov %edi,%eax 12: c1 e8 07 shr $0x7,%eax 15: 83 e0 01 and $0x1,%eax 18: c3 retq |
|
05-05-2020, 19:27 | #15 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3594
|
siete andati avanti, grandi
Io sto usando quella verifica in un Codice:
while(variabile < 0x80) { ...... } Ultima modifica di misterx : 05-05-2020 alle 19:32. |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 08:21.