Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Uso creativo di void*
Forum - C/C++ - Uso creativo di void* - Pagina 2

Pagine: [ 1 2 3 4 ] Precedente | Prossimo
Avatar
lumo (Member)
Expert


Messaggi: 449
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 23:54
Mercoledì, 12/07/2017
L'algoritmo è abbastanza ingegnoso, però quei commenti sono inutili (descrivono operazioni banali) e soprattutto non fanno capire come funziona il codice.
Ad esempio perché quando fai *pm++ = *po++; sei sicuro che su *pm non ci sia un valore che magari viene sovrascritto?
Questa è la parte interessante e merita un commento, di al più una riga, il resto è fuffa.

Comunque puoi usare void** in questo caso:
Codice sorgente - presumibilmente C/C++

  1. void **po = (void**) array;
  2. void **pm = (void**) array;



Il po++ dopo l'else mi fa venire l'urticaria, ti prego va a capo :(
E l'else dopo il return l; è inutile, toglilo (e va a capo!!).

Una cosa, (size_t) - 1 va bene ma se vuoi essere proprio figo puoi fare, includendo <stdint.h>
Codice sorgente - presumibilmente C/C++

  1. return SIZE_MAX;



Poi su printf non so perché il compilatore non te lo segnali, ma per i size_t devi usare %zu
Inoltre io per i puntatori in genere uso %p , anche perché su una macchina a 64 bit non bastano 8 caratteri esadecimali per rappresentare un indirizzo. Inoltre, almeno per me, %p aggiunge 0x automaticamente (la rapprentazione dovrebbe essere adeguata al sistema operativo/architettura in modo automatico).

Un quicksort come dice thedarkjuster funzionerebbe, ma questo algoritmo è migliore perché è O(n) invece che O(n log n)

Ultima modifica effettuata da lumo il 12/07/2017 alle 23:55
PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 20:30
Giovedì, 13/07/2017
Ora penso ai tanti consigli che mi avete dato e faccio qualche prova, poi torno a commentare.

Nel frattempo, lumo, avevo letto cose turpi contro all'uso di void**... dici invece che posso usarlo senza patemi (almeno in questo caso)? Come sai mi fido parecchio dei tuoi consigli. In ogni caso, anche su questo farò testè delle prove, poi torno. (visto quanto sono creativo con le concordanze dei verbi?)

Edit: aggiungo subito una cosa -- i commenti servono principalmente a me, per evitare di perdere la trebisonda mentre (s)ragiono.

Edit II: %zu me lo segnala come "warning: unknown conversion type character 'z' in format".

Edit III: meno male che mi hai spinto a ripensarci! c'era uno scarafaggione grande quando una bmw (TheDarkJuster ha il naso fino)! Ora dovrebbe andare meglio:

Codice sorgente - presumibilmente C#

  1. size_t accoda_puntatori_nulli( void *array, size_t qEl ) {
  2.     if( array ) {
  3.         void **po = (void**) array; /* per scorrere l'array originale */
  4.         void **pm = (void**) array; /* per scorrere l'array modificato */
  5.  
  6.         for( ; qEl--; ++po ) {
  7.             if( *po != NULL ) {
  8.                 if( *pm == NULL ) {
  9.                     *pm = *po;
  10.                     *po = NULL;
  11.                 }
  12.  
  13.                 ++pm;
  14.             }
  15.         }
  16.  
  17.         return pm-((void**)array); /* restituisce la lunghezza dell'array */
  18.     }
  19.  
  20.     return SIZE_MAX; /* valore massimo per size_t: errore */
  21. }


Ultima modifica effettuata da AldoBaldo il 13/07/2017 alle 21:59


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 449
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 22:46
Giovedì, 13/07/2017
Strano il warning, ho provato con gcc 5.4 e clang 3.8 e entrambi mi danno warning se NON uso %zu.
Comunque non sono sicuro che if (*pm == NULL) sia proprio necessaria, l'unico caso in cui ci dovrebbe essere una copia con *pm nullo dovrebbe essere quando pm e po puntano entrambi sullo stesso elemento non nullo, quindi al massimo hai una copia in più (difficile dire se sia peggio questo o un if, di solito io faccio felice il branch predictor e tolgo gli if).

PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 23:31
Giovedì, 13/07/2017
Eliminando (*pm==NULL) finisce per sovrascrivere il puntatore eventualmente presente in prima posizione nell'array.

Per quel che riquarda %zu... non è che sia tratta di un identificatore aggiunto in qualche versione del C successiva a quella che sto usando?

Edit: Così funziona, però non credo che sia chissà quanto diverso quando il compilatore lo trasforma in linguaggio-macchina. E' ben vero che ridurre tutto in così poche righe fa un bel po' figo, eh!

Codice sorgente - presumibilmente C#

  1. size_t accoda_puntatori_nulli( void *array, size_t qEl ) {
  2.     if( array ) {
  3.         void **po = (void**) array; /* per scorrere l'array originale */
  4.         void **pm = (void**) array; /* per scorrere l'array modificato */
  5.  
  6.         for( ; qEl--; ++po )
  7.             if( *po != NULL )
  8.                 pm += *pm==NULL ? *pm=*po,*po=NULL,1 : 1;
  9.  
  10.         return pm-((void**)array); /* restituisce la lunghezza dell'array */
  11.     } else return SIZE_MAX; /* valore massimo per size_t: errore */
  12. }


Ultima modifica effettuata da AldoBaldo il 13/07/2017 alle 23:41


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 449
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 23:48
Giovedì, 13/07/2017
Testo quotato

Postato originariamente da AldoBaldo:

Eliminando (*pm==NULL) finisce per sovrascrivere il puntatore eventualmente presente in prima posizione nell'array.


Hai ragione, in effetti un modo per risolvere senza if sarebbe questo (non testato!):
Codice sorgente - presumibilmente C/C++

  1. while (qEl--) {
  2.             if( *po != NULL ) {
  3.                 void* tmp = *po;
  4.                 *po = *pm;
  5.                 *pm = tmp;
  6.                 ++pm;
  7.             }
  8.             ++po;
  9.         }



Testo quotato


Per quel che riquarda %zu... non è che sia tratta di un identificatore aggiunto in qualche versione del C successiva a quella che sto usando?



Sono andato a guardare lo standard[0] C99 e a pagina 289 trovo z per size_t.
In effetti non mi pare di vederlo in C89 (http://port70.net/~nsz/c/c89/c89-draft.html#4.9.6.1) ma dubito che tu stia usando uno standard così vecchio, sarebbe bello vedere che mingw hai su codeblocks.

[0] http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf

PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 23:58
Giovedì, 13/07/2017
Attivando C99 nell'IDE %zu viene accettato senza proteste.

============================

Il compilatore è gcc qualcosa:

Codice sorgente - presumibilmente C/C++

  1. //=== TDM-GCC Compiler Suite for Windows ===
  2. //---           GCC 4.9 Series           ---
  3. //***   Standard MinGW 32-bit Edition    ***



Più precisamente, trovo in un oscuro file d'accompagnamento che la versione è GCC 4.9.2

============================

In pratica invece di fare una sostituzione fai uno swap dei valori di *po e *pm...

Ultima modifica effettuata da AldoBaldo il 14/07/2017 alle 0:02


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 0:02
Venerdì, 14/07/2017
-STD=c99 e se nessuno di lamenta tutti sono felici.
Se il compilatore non supporta quello standard hai un GCC antico.

Comunque felice di esserti stato utile. Quando posso ti scrivo la funzione come la farei io.... Ti avviso che potrebbe essere molto diversa...
Mi prenderò la libertà di cambiare i parametri in ingresso, perché con un void* non mi ci trovo proprio...

PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 0:32
Venerdì, 14/07/2017
Codice sorgente - presumibilmente C++

  1. size_t accoda_puntatori_nulli( void *array, size_t qEl ) {
  2.     if( array ) {
  3.         void **po = (void**) array; /* per scorrere l'array originale */
  4.         void **pm = (void**) array; /* per scorrere l'array modificato */
  5.         void *pTmp;                 /* per lo scambio dei puntatori */
  6.  
  7.         while( qEl-- ) /*     |=========swap=========|   |=inc=|  |inc|      */
  8.             po  +=  *po  ?  pTmp=*po, *po=*pm, *pm=pTmp, ++pm, 1  :  1;
  9.  
  10.         return pm-((void**)array); /* restituisce la lunghezza dell'array */
  11.     }
  12.  
  13.     return SIZE_MAX; /* valore massimo per size_t: errore */
  14. }



Sempre meno righe!!! :k:

TheDarkJuster, avrai capito che quel che mi suggerisce si "attacca" al 90%. Non dico d'essere chissà che mostro d'apprendimento, però cerco di far tesoro dei suggerimenti che mi arrivano da chi ne sa più di me. Quando non lo faccio è 1) perché me ne dimentico ( Alzheimer :pat: ) o 2) perché proprio non mi ci trovo e mi confondo ( in genere, però, dopo un po' decanto e le cose entrano comunque in qualche neurone sparso, ramingo e solitario ).

Ultima modifica effettuata da AldoBaldo il 14/07/2017 alle 0:34


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Pagine: [ 1 2 3 4 ] Precedente | Prossimo