C, matrici, allocazione dinamica ed eleganza del codice.

di il
50 risposte

50 Risposte - Pagina 3

  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    IfNotFalseTrue ha scritto:


    Non so che dirti, usare __STDC_VERSION__ probabilmente non è una buona idea, per l'ANSI C perché lo standard non dice nulla al riguardo quindi potrebbe esistere con un valore diverso da quello che ti aspetti.
    In pratica tu vorresti controllare gli argomenti che uno utilizza per compilare il suddetto codice? Puoi spiegare meglio cosa intendi?
    Certo! Dovrei innanzitutto controllare la versione dello standard utilizzata, e se mi dici così potrebbe risultare più complicato del previsto il detect del C90. Se riuscissi a comprendere di stare compilando in C90 nemmeno ci provo ad utilizzare i pointer-to-VLA.
    Se invece scopro di stare compilando in C99 o in C11 non è detto che abbia i VLA abilitati. Potrebbe essere stata specificata la macro che dicevi tu, STDNOVLA, ma essa è valida solo in C11 e potrebbe portare errori in C90 e in C99 come potrebbe portarne STDVERSION in C90.
    Per giunta potrei aver compilato in C11/C99 usando il flag -Werror=vla, il quale macro o non macro, mi pare di capire che blocchi del tutto l'uso dei VLA. Sicuramente in C11 perché l'ho testato, direi anche in C99 visto che l'errore sollevato in C11 è quello di una non corretta corrispondenza con l'ISO90. Come potrei fare a risolvere anche questo problema? Si parla di un flag che viene inserito quando si esegue il compilatore, quindi l'unico modo penso sia quello di controllare *argv[] con il preprocessore. Aggiungo che se il supporto ai VLA del C11 è basato, se non ho capito male, su alcuni flag inseriti in automatico (però non ne sono affatto sicuro) potrei risolvere tutti i problemi controllando la presenza o la assenza di determinati flag dal preprocessore.
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    Aggiungo una richiesta ai più esperti. Nel lontano 99 come eseguivate un controllo per le nuove features del C99 rispetto al C90? Come eseguivate il controllo della versione del compilatore/dello standard C usato se la macro STDCVERSION non era presente nel C90? Curiosità personale che potrebbe essermi di aiuto almeno per risolvere il problema del C90.
    Purtroppo nel 1999 io ero troppo impegnato ad avere due anni per potermi interessare del C.
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    jfet ha scritto:


    Aggiungo una richiesta ai più esperti. Nel lontano 99 come eseguivate un controllo per le nuove features del C99 rispetto al C90?
    Semplice, nessuno lo faceva, nessuno se ne preoccupava (o quasi).
    Soprattutto nessuno (o quasi) si interessava, e lo fa anche oggi, di tutta la "croppa" che man mano è stata aggiunta a C/C++.
    La quale è "bannata" per lo sviluppo in buona parte delle software house, anche le più grandi.

    Nessuno (o quasi) ha tempo o voglia di farsi le "pippe" mentali per i 1000 tipi di compilatori e i 1000 dialetti più o meno compatibili tra di loro.

    Si lavorava (e lo si fa tutt'ora) col sottoinsieme minimo che sicuramente funziona, lasciando perdere le "novità" che da me funzionano, da te forse, oggi chissà, domani sarà magari deprecato.

    Il linguaggio è solo lo strumento per fare qualcosa (il programma vero e proprio): risparmiare su 100.000 righe di codice [][] non è diciamo la priorità maggiore
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    +m2+ ha scritto:


    jfet ha scritto:


    Aggiungo una richiesta ai più esperti. Nel lontano 99 come eseguivate un controllo per le nuove features del C99 rispetto al C90?
    Semplice, nessuno lo faceva, nessuno se ne preoccupava (o quasi).
    Soprattutto nessuno (o quasi) si interessava, e lo fa anche oggi, di tutta la "croppa" che man mano è stata aggiunta a C/C++.
    La quale è "bannata" per lo sviluppo in buona parte delle software house, anche le più grandi.

    Nessuno (o quasi) ha tempo o voglia di farsi le "pippe" mentali per i 1000 tipi di compilatori e i 1000 dialetti più o meno compatibili tra di loro.

    Si lavorava (e lo si fa tutt'ora) col sottoinsieme minimo che sicuramente funziona, lasciando perdere le "novità" che da me funzionano, da te forse, oggi chissà, domani sarà magari deprecato.

    Il linguaggio è solo lo strumento per fare qualcosa (il programma vero e proprio): risparmiare su 100.000 righe di codice [][] non è diciamo la priorità maggiore
    Ahahhaahhahaha non potevo sperare in risposta migliore. Purtroppo per me adesso è diventata una questione di principio che voglio risolvere
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    jfet ha scritto:


    Ahahhaahhahaha non potevo sperare in risposta migliore. Purtroppo per me adesso è diventata una questione di principio che voglio risolvere
    Se vuoi parto col "pippone" sulla contaminazione C/C++ e soprattutto, in questo caso, delle Grandi Aggiunte a C99 (essenzialmente il tentativo abortito di avere vettori "davvero" a lunghezza variabile) e a C11 (il tentativo, nuovamente abortito, di avere un "qualcosa" contro i buffer overflow).

    Insomma al 99% è croppa che il programmatore di medio livello evita come la peste, facendosi magari le SUE funzioncelle di supporto che funzionano sempre (si spera) invece di ... chi può dirlo?

    Ci sono stati dibattiti ferocissimi durati decenni (ancora in corso) su cosa e perchè includere in un linguaggio, e come e perchè usarlo, e magari deprecarlo ed eliminarlo dal successivo standard.

    Visto che sei giovincello ti do una delle varie Perle Dell'Informatica:

    se è semplice, FORSE funziona

    vabbè prima di andar via, ecco uno degli esempi più clamorosi.

    come funziona strncpy_s rispetto a strncpy ? Non proprio come uno se lo potrebbe aspettare (e via di voragini di sicurezza, funzionamenti anomali e difficilissimi da individuare, eccetera).
    Un indizio: qualche "genio" ha deciso che visto che i programmi non hanno bug, per azzerare un buffer che contiene una stringa basta scriverci un NUL
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    +m2+ ha scritto:


    jfet ha scritto:


    Ahahhaahhahaha non potevo sperare in risposta migliore. Purtroppo per me adesso è diventata una questione di principio che voglio risolvere
    Se vuoi parto col "pippone" sulla contaminazione C/C++ e soprattutto, in questo caso, delle Grandi Aggiunte a C99 (essenzialmente il tentativo abortito di avere vettori "davvero" a lunghezza variabile) e a C11 (il tentativo, nuovamente abortito, di avere un "qualcosa" contro i buffer overflow).

    Insomma al 99% è croppa che il programmatore di medio livello evita come la peste, facendosi magari le SUE funzioncelle di supporto che funzionano sempre (si spera) invece di ... chi può dirlo?

    Ci sono stati dibattiti ferocissimi durati decenni (ancora in corso) su cosa e perchè includere in un linguaggio, e come e perchè usarlo, e magari deprecarlo ed eliminarlo dal successivo standard.

    Visto che sei giovincello ti do una delle varie Perle Dell'Informatica:

    se è semplice, FORSE funziona

    vabbè prima di andar via, ecco uno degli esempi più clamorosi.

    come funziona strncpy_s rispetto a strncpy ? Non proprio come uno se lo potrebbe aspettare (e via di voragini di sicurezza, funzionamenti anomali e difficilissimi da individuare, eccetera).
    Un indizio: qualche "genio" ha deciso che visto che i programmi non hanno bug, per azzerare un buffer che contiene una stringa basta scriverci un NUL
    I pipponi sono sempre i benvenuti purché qualcuno si degni comunque di aiutarmi con il problema
    p.s. la lezione la inciderò col cutter sull' lcd del PC, giusto per averla sempre presente XD
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    +m2+ ha scritto:


    qualche "genio" ha deciso che visto che i programmi non hanno bug, per azzerare un buffer che contiene una stringa basta scriverci un NUL
    Come non lo sai? I bug sono per gli stolti, i veri programmatori creano features
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    jfet ha scritto:


    È un syntatic sugar, permette di mantenere la sintassi utilizzata per accedere agli elementi di array, matrici, ecc statici allocando comunque un unico, contiguo blocco di memoria dinamico.
    Si, infatti sarebbe una gran bella comodità quella di poter utilizzare la notazione arr[j] anziché *(arr+i*col+j)); ma ora mi è venuto un dubbio: sei sicuro che stai allocando tutto sull'heap?

    Con la tua scrittura: int(*matrix)[c] = allocate(r, c); secondo me (ma potrei sbagliarmi) stai allocando le colonne sullo stack con [c] e le righe sullo heap con malloc.

    Prova a scrivere: int(*matrix)[c] = allocate_row(r);
    con: int (*allocate_row(unsigned r))[]{ return malloc(r * sizeof(int)); }
    in modo che l'allocazione con malloc sia solo per le righe.
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    Unqualunque ha scritto:


    jfet ha scritto:


    È un syntatic sugar, permette di mantenere la sintassi utilizzata per accedere agli elementi di array, matrici, ecc statici allocando comunque un unico, contiguo blocco di memoria dinamico.
    Si, infatti sarebbe una gran bella comodità quella di poter utilizzare la notazione arr[j] anziché *(arr+i*col+j)); ma ora mi è venuto un dubbio: sei sicuro che stai allocando tutto sull'heap?

    Con la tua scrittura: int(*matrix)[c] = allocate(r, c); secondo me (ma potrei sbagliarmi) stai allocando le colonne sullo stack con [c] e le righe sullo heap con malloc.

    Prova a scrivere: int(*matrix)[c] = allocate_row(r);
    con: int (*allocate_row(unsigned r))[]{ return malloc(r * sizeof(int)); }
    in modo che l'allocazione con malloc sia solo per le righe.


    Si ne sono sicuro perché l'allocazione la fa la malloc Guarda il calcolo della malloc... è r * c * sizeof(unsigned)...
    unsigned(*matrix)[c] è solo una dichiarazione di puntatore che non è molto diversa da quella di un puntatore a funzione. Sempre 4 oppure 8 byte sono. Semplicemente quello che inserisci tra parentesi punta a ciò che sta fuori, in questo caso non a una funzione ma un blocco di unsigned. Quanti unsigned? Nel mio caso il tipo non è completamente noto a compiletime. Lo sa a runtime quanto vale "c" e quindi come eseguire un'istruzione tipo matrix+1; ovvero quanti unsigned "saltare" in avanti o indietro.
    Infatti puoi compilare tranquillamente:
    
    unsigned n = 0;
    scanf("%u", &n);
    (unsigned)(*p)[n];
    
    Per poi inserire 3 miliardi in ingresso. Allocherai pur sempre 8 byte per p e basta. Non verrà allocato in automatico spazio per 3 miliardi di byte sullo stack, ci mancherebbe. Semplicemente n definisce l'aritmetica per il puntatore p. In modo da trattare espressioni come p+N, p-N e p[N]. Comunque probabilmente non è più una buona idea fare p+1; data l'enorme dimensione di n, ma questo è solo un esempio.
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    Si, in effetti ho controllato. Gli indirizzi restituiti dai puntatori, sia delle righe che delle colonne, sono entrambi indirizzi che risiedono sullo heap.
    Nel mio test funzionava anche se allocavo solo le righe: int(*matrix)[c] = allocate_row(r); ma probabilmente il processo andava a scrivere e a leggere in overrun su locazioni inutilizzate, senza conseguenze.

    Beh, io l'ho aggiunto tra i miei appunti come "metodo No 5)" nella lista dei metodi per la gestione delle matrici, e ad essere sincero lo preferirei agli altri, per oggetti di grandi dimensioni, perché permette la notazione a[j] con allocazione di un unico blocco di memoria contigua sull'heap.
    Poi se altri compilatori non lo eseguono, amen, lo terrò per progetti privati annotando: // C99 only!
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    Unqualunque ha scritto:


    Probabilmente il processo andava a scrivere e a leggere in overrun su allocazioni inutilizzate, senza conseguenze.

    Si si, perché comunque non allocavi sufficiente spazio.

    Unqualunque ha scritto:


    ad essere sincero lo preferirei agli altri
    Mi sento onorato!!!

    Unqualunque ha scritto:


    Poi se altri compilatori non lo eseguono, amen, lo terrò per progetti privati annotando: // C99 only!
    Beh se mi dassi una manina per questo problemuccio non sarebbe male ehehehe; verificare di stare compilando in C99 sarebbe già un buon passo avanti visto che in C90 la macro STDCVERSION non è definita.
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    Ho compilato con PellesC in C99. Compila ed esegue anche impostando C11.
    Livello di warning massimo: nessun warning che riguardasse la notazione in questione.
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    Scusate burdèl, ma nel "mondo normale" si fanno funzioncelle di astrazione simil-C++ ( per modo di dire ).
    Le chiamerete qualcosa tipo

    scrivimatrice (matrice,i,j,valore)
    leggimatrice (matrice,i,j)

    all'interno ci saranno i vari controlli (matrice esistente, valori i e j positivi e <dimensione massima) eccetera.
    difficilmente ci si pone il "dramma esistenziale" di roba più o meno complicata, più o meno compatibile, più o meno portabile, più o meno affidabile.

    se, un domani, porterai a C++ avrai due banali setter-getter (mai e poi mai overload degli operatori).
    altrimenti "vivrai felice", con una sorta di funzioni _s (alla C11), che però saranno sotto il tuo controllo
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    Unqualunque ha scritto:


    Ho compilato con PellesC in C99. Compila ed esegue anche impostando C11.
    Livello di warning massimo: nessun warning che riguardasse la notazione in questione.
    Prova ad aggiungere il flag -Werror=vla, vorrei provare ad aggiungere questo controllo...dopo aver capito di non stare compilando in C90.
  • Re: C, matrici, allocazione dinamica ed eleganza del codice.

    +m2+ ha scritto:


    Scusate burdèl, ma nel "mondo normale" si fanno funzioncelle di astrazione simil-C++ ( per modo di dire ).
    Le chiamerete qualcosa tipo

    scrivimatrice (matrice,i,j,valore)
    leggimatrice (matrice,i,j)

    all'interno ci saranno i vari controlli (matrice esistente, valori i e j positivi e <dimensione massima) eccetera.
    difficilmente ci si pone il "dramma esistenziale" di roba più o meno complicata, più o meno compatibile, più o meno portabile, più o meno affidabile.

    se, un domani, porterai a C++ avrai due banali setter-getter (mai e poi mai overload degli operatori).
    altrimenti "vivrai felice", con una sorta di funzioni _s (alla C11), che però saranno sotto il tuo controllo
    Si immagino che il mondo normale sia differente, ma come ti dicevo è diventata più una questione di principio che altro ahahaha
Devi accedere o registrarti per scrivere nel forum
50 risposte