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++ - Matrice dinamica e void* in C - cast o non cast?
Forum - C/C++ - Matrice dinamica e void* in C - cast o non cast? - Pagina 2

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 23:26
Venerdì, 07/04/2017
Sì, quello è un approccio che son solito usare (e funziona). Questa volta però avevo in mente di fare qualcosa di utilizzabile nella forma matrice[][], che in certe circostanze è più "comodo" perché appare più esplicito.


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
Template (Member)
Pro


Messaggi: 177
Iscritto: 09/12/2015

Segnala al moderatore
Postato alle 23:50
Venerdì, 07/04/2017
Probabilmente pensandoci arriverai a moltissimi possibili algoritmi... ma di fatto, credo che la soluzione migliore rimanga il casting esplicito.

PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 0:16
Sabato, 08/04/2017
Però nella pagina di Stack Overflow che mi hai segnalato non sono pochi coloro che mettono in guardia dalla possibilità di "falle" nell'effettuare cast di puntatori a doppia indirezione void**. Personalmente ho sempre pensato che un puntatore fosse solo un numero che indica una posizione in memoria, secondo le "dimensioni" di indirizzamento del sistema in uso (nel mio caso, 32 bit). Dunque, se il ragionamento regge, una puntatore a doppia indirezione è un numero che dice dove andare a guardare in memoria per trovare un altro numero che dice dove trovare in memoria un certo dato. Un po' intricata come espressione, ma CREDO realistica. Questo parrebbe lasciare intendere che fare un cast a un puntatore non crei chissà quali sfaceli. Epperò su Stack Overflow, se ho bene inteso, un tale osserva che gli sfaceli possono derivare dall'eventuale ricorso malaccorto all'aritmetica sui puntatori, il che mi sembra effettivamente plausibile. Che grana!


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
Template (Member)
Pro


Messaggi: 177
Iscritto: 09/12/2015

Segnala al moderatore
Postato alle 7:47
Sabato, 08/04/2017
Si, l'uso dei puntatori non è sempre banale e privo di rischi... ma soppesando vantaggi e svantaggi, un po' di rischio potrebbe essere preferibile ad algoritmi molto più complessi (leggi: molto più soggetti a bug ed errori).

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 10:03
Sabato, 08/04/2017
Il problema fondamentale di chi usa (male) i puntatori è proprio il fatto che sottovaluta (o non sa) che dietro c'è una "aritmetica dei puntatori" che governa tante operazioni e che, al contrario, il compilatore lo tiene sempre in considerazione.


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 17:51
Sabato, 08/04/2017
Ho deciso che, per la sua semplicità, userò la soluzione che ho indicato nel codice incluso nel commento delle 22:35 del 7/4. Grazie a tutti quelli che mi hanno dedicato il loro tempo. In particolare a chi mi ha messo la "pulce nell'orecchio" sulla questione della doppia indirezione su void, della quale non sapevo NULLA. Ora, se non altro, so di non sapere (e non è cosa da poco, perché mi evita il rischio di fare delle stupidaggini troppo grandi).

Ultima modifica effettuata da AldoBaldo il 08/04/2017 alle 17:53


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 18:03
Sabato, 08/04/2017
Potresti rendere un po' meno copia-incolla quella soluzione usando le macro
Codice sorgente - presumibilmente C#

  1. #define DECLARE_MATRIX(type)
  2. type **crea_matrice_##type ( uint32_t qRighe, uint32_t qColonne ) {
  3.     // alloca i puntatori alle righe, tutti NULL
  4.     type **matrice = calloc( qRighe, sizeof(type*) );
  5.  
  6.     if( matrice != NULL ) { // se l'allocazione e' riuscita...
  7.         uint32_t r; // contatore
  8.  
  9.         for( r=0; r<qRighe; ++r ) { // per ogni riga
  10.             // alloca in blocco tutte le colonne sulla riga
  11.             matrice[r] = calloc( qColonne, sizeof(*matrice[r])*qColonne );
  12.  
  13.             if( matrice[r] == NULL ) { // se l'allocazione NON e' riuscita...
  14.                 distruggi_matrice_##type ( &matrice, r );
  15.                 break;
  16.             }
  17.         }
  18.     }
  19.  
  20.     return matrice; // NULL in caso d'errore
  21. }



Ho omesso il \ a fine riga per pigrizia ma senza non funzionerebbe.
Sotto quella dovresti mettere anche distruggi_matrice_##type

Così ogni volta che ti serve una matrice di quel tipo fai:

Codice sorgente - presumibilmente Plain Text

  1. DECLARE_MATRIX(char)



nello scope globale, e poi puoi utilizzare le funzioni crea_matrice_char e distruggi_matrice_char. Ha l'ovvio svantaggio che per tipi complessi devi usare un typedef, inoltre io lo trovo un po' difficile da leggere.
Del resto il C è più a suo agio quando si sta vicini alla macchina, per la programmazione ad alto livello mostra un po' gli anni.

Testo quotato


Intendi così...

void **crea_matrice( size_t dim_el, uint32_t n_righe, uint32_t n_colonne );

... o così?

void **crea_matrice( size_t dim_el, size_t n_righe, size_t n_colonne );



La seconda, infatti è anche il tipo che accettano malloc e calloc. Quando si ha a che fare con una grandezza riferita alla memoria indirizzabile si usa sempre size_t per far capire che è quello l'intento.

PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 19:54
Sabato, 08/04/2017
Bene, allora vada per i size_t!

Per quel che riguarda usare una macro così articolata...
...a parte che mi sfuggono alcuni dettagli formali che mi vado a rivedere subito, non è che ogni volta che la usi finisci per inserire una quantità considerevole di codice inline duplicato nell'eseguibile? Avevo letto da qualche parte che le macro sono convenienti in termini prestazionali ma, se il codice rappresentato è ampio, inducono un rapido ingigantimento dell'eseguibile.

Vado a rivedere quei dettagli formali, va, se no mi sa che rischio di scrivere delle corbellerie.


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 ] Precedente | Prossimo