Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Le soluzioni FSP per il 2026: potenza e IA al centro
Le soluzioni FSP per il 2026: potenza e IA al centro
In occasione del Tech Tour 2025 della European Hardware Association abbiamo incontrato a Taiwan FSP, azienda impegnata nella produzione di alimentatori, chassis e soluzioni di raffreddamento tanto per clienti OEM come a proprio marchio. Potenze sempre più elevate negli alimentatori per far fronte alle necessità delle elaborazioni di intelligenza artificiale.
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa
AWS è il principale operatore di servizi cloud al mondo e da tempo parla delle misure che mette in atto per garantire una maggiore sovranità alle organizzazioni europee. L'azienda ha ora lanciato AWS European Sovereign Cloud, una soluzione specificamente progettata per essere separata e distinta dal cloud "normale" e offrire maggiori tutele e garanzie di sovranità
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto
Xiaomi ha portato sul mercato internazionale la nuova serie Redmi Note, che rappresenta spesso una delle migliori scelte per chi non vuole spendere molto. Il modello 15 Pro+ punta tutto su una batteria capiente e su un ampio display luminoso, sacrificando qualcosa in termini di potenza bruta e velocità di ricarica
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 27-04-2020, 10:25   #1
misterx
Senior Member
 
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3741
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 13:30.
misterx è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2020, 13:57   #2
misterx
Senior Member
 
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3741
risolto ho preso un abbaglio
misterx è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2020, 22:22   #3
Lampo89
Member
 
L'Avatar di Lampo89
 
Iscritto dal: Dec 2006
Messaggi: 33
Ciao,

Quote:
Originariamente inviato da misterx Guarda i messaggi
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++;
}
sì è corretto come da specifiche. Nel primo caso hai appunto definito una variabile globale che è visibile anche in tutte le translation units grazie alla magica magia del linker. Nel secondo caso, vale la semantica pass-by-value solita: alla chiamata di una funzione viene creato un nuovo stack frame in cui sono copiati il valore dei parametri passati.
Morale della favola: meglio evitare, se possibile, variabili globali ...
Lampo89 è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2020, 08:29   #4
misterx
Senior Member
 
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3741
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.
misterx è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2020, 12:48   #5
misterx
Senior Member
 
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3741
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;
misterx è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2020, 19:21   #6
wingman87
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2786
Quote:
Originariamente inviato da misterx Guarda i messaggi
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.
Invece di passare il valore della variabile, puoi passare l'indirizzo della variabile
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)++;
}
Ho messo le parentesi in (*pippo)++; perché non ricordo la precedenza degli operatori, nel dubbio con le parentesi non ci sono equivoci.
Quote:
Originariamente inviato da misterx Guarda i messaggi
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;
Forse perché questo è un modo generico di ottenere il valore del bit n+1 all'interno del byte (nel tuo esempio n=7). Inoltre dovrebbe funzionare anche per tipi di variabili signed e con più byte, tipo int (scusa se uso il condizionale ma vado a memoria).
wingman87 è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2020, 19:50   #7
misterx
Senior Member
 
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3741
Quote:
Originariamente inviato da wingman87 Guarda i messaggi
Invece di passare il valore della variabile, puoi passare l'indirizzo della variabile
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)++;
}
Ho messo le parentesi in (*pippo)++; perché non ricordo la precedenza degli operatori, nel dubbio con le parentesi non ci sono equivoci.

Forse perché questo è un modo generico di ottenere il valore del bit n+1 all'interno del byte (nel tuo esempio n=7). Inoltre dovrebbe funzionare anche per tipi di variabili signed e con più byte, tipo int (scusa se uso il condizionale ma vado a memoria).

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
misterx è offline   Rispondi citando il messaggio o parte di esso
Old 29-04-2020, 09:36   #8
misterx
Senior Member
 
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3741
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
misterx è offline   Rispondi citando il messaggio o parte di esso
Old 30-04-2020, 04:28   #9
frncr
Senior Member
 
Iscritto dal: May 2009
Messaggi: 904
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.
frncr è offline   Rispondi citando il messaggio o parte di esso
Old 30-04-2020, 11:36   #10
misterx
Senior Member
 
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3741
grazie per la conferma
misterx è offline   Rispondi citando il messaggio o parte di esso
Old 01-05-2020, 13:51   #11
Volutomitra
Member
 
Iscritto dal: Feb 2006
Messaggi: 134
Quote:
Originariamente inviato da misterx Guarda i messaggi
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;
Io farei, e di solito faccio, così:

(miobyte & 0x80)

Ma ragiono per microcontrollori, dove sprecare operazioni inutili è un delitto
Volutomitra è offline   Rispondi citando il messaggio o parte di esso
Old 03-05-2020, 10:09   #12
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 12936
Quote:
Originariamente inviato da Volutomitra Guarda i messaggi
Io farei, e di solito faccio, così:

(miobyte & 0x80)

Ma ragiono per microcontrollori, dove sprecare operazioni inutili è un delitto
Sono sempre per la soluzione che è più facile da leggere, come la tua .

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 10:16. Motivo: precisazioni su complemento a 2
WarDuck è online   Rispondi citando il messaggio o parte di esso
Old 04-05-2020, 15:28   #13
Volutomitra
Member
 
Iscritto dal: Feb 2006
Messaggi: 134
Quote:
Originariamente inviato da WarDuck Guarda i messaggi
Sono sempre per la soluzione che è più facile da leggere, come la tua .

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
Siccome sono un rompiballe sono andato a vedere

Codice:
unsigned char test1(unsigned char value) {
    return (value & 0x80);
}

unsigned char test2(unsigned char value) {
    return ((value >> 7) & 1);
}
compilando con gcc x86-64 9.3, diventa:

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
Ho evidenziato le istruzioni corrispondenti ai rispettivi return. Il verdetto è che WarDuck ha ragione, il compilatore ottimizza.

Resta il fatto che ovviamente anche per me la prima versione è più leggibile

Quote:
Originariamente inviato da WarDuck Guarda i messaggi
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.
In questo caso avevo ovviamente dato per scontato che il tipo byte fosse unsigned char...
Volutomitra è offline   Rispondi citando il messaggio o parte di esso
Old 05-05-2020, 20:16   #14
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 12936
Quote:
Originariamente inviato da Volutomitra Guarda i messaggi
Siccome sono un rompiballe sono andato a vedere

Codice:
unsigned char test1(unsigned char value) {
    return (value & 0x80);
}

unsigned char test2(unsigned char value) {
    return ((value >> 7) & 1);
}
compilando con gcc x86-64 9.3, diventa:

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
Ho evidenziato le istruzioni corrispondenti ai rispettivi return. Il verdetto è che WarDuck ha ragione, il compilatore ottimizza.

Resta il fatto che ovviamente anche per me la prima versione è più leggibile
C'è da dire che i due codici non sono perfettamente equivalenti, la prima funzione ritorna 0 oppure 0x80, mentre la seconda 0 oppure 1.

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);
}
Si ottiene lo stesso assembly (GCC 9.2.x):
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
È interessante anche notare che l'AND 1 viene eliminato dalla seconda funzione. Questo succede perché entrambi i tipi, del valore e di ritorno sono "unsigned char" e si fa uno shift di 7 quindi il compilatore sà per certo che nell'output tutti i bit eccetto il primo sono 0, rendendo non necessario l'AND.

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
Le bellezze di GCC
WarDuck è online   Rispondi citando il messaggio o parte di esso
Old 05-05-2020, 20:27   #15
misterx
Senior Member
 
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3741
siete andati avanti, grandi

Io sto usando quella verifica in un

Codice:
while(variabile < 0x80)
{ ...... }
ed ho notato in definitiva svolge lo stesso compito

Ultima modifica di misterx : 05-05-2020 alle 20:32.
misterx è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Le soluzioni FSP per il 2026: potenza e IA al centro Le soluzioni FSP per il 2026: potenza e IA al ce...
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa AWS annuncia European Sovereign Cloud, il cloud ...
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto Redmi Note 15 Pro+ 5G: autonomia monstre e displ...
HONOR Magic 8 Pro: ecco il primo TOP del 2026! La recensione HONOR Magic 8 Pro: ecco il primo TOP del 2026! L...
Insta360 Link 2 Pro e 2C Pro: le webcam 4K che ti seguono, anche con gimbal integrata Insta360 Link 2 Pro e 2C Pro: le webcam 4K che t...
Ubisoft ha definitivamente archiviato Wa...
Motivair by Schneider Electric presenta ...
Un dissipatore che non richiede energia ...
Con Maia 200 Microsoft alza l'asticella ...
La Cina impone requisiti anche per lo st...
Apple lancia AirTag aggiornato: range es...
Microsoft risolve i blocchi di Outlook: ...
OpenAI verso il disastro finanziario? L’...
X nei guai: l'UE indaga sui pericoli del...
Caso Corona-Signorini: il giudice blocca...
470 petaFLOPS con una frequenza di 56 GH...
WhatsApp: abbonamento per rimuovere la p...
Xiaomi Redmi Note 15 in promozione: smar...
NVIDIA investe 2 miliardi in CoreWeave: ...
Chery lancia con Lepas la piattaforma LE...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 19:29.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v