RISOLTO Strano comportamento semplice codice C++

Stato
Discussione chiusa ad ulteriori risposte.

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,208
1,845
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Non penso lo riconosceranno come errore, magari terranno conto del caso limite ed implementeranno un fix...il motivo è che questo funge

C++:
unsigned int cnt = 0;  

for (unsigned int i = 0; i < 3; i++) {      
    for (unsigned int j = 0; j < 3; j++) {          
        if (m[i][j].flag || m[i][j].v.size()) cout << cnt++ << endl;           
    }  
}

cioè dal punto di vista semantico è il codice originale che cerca di infilarsi "sotto il cofano" della gestione degli array, cosa che idiomaticamente non dovrebbe fare

voglio dire, se hanno implementato l'allocazione degli elementi degli array multidimensionali in "modo strano" nel caso -O3, ci saranno ragioni prestazionali, non è una svista

Si, e come ho mostrato sopra funziona anche questo, che è una variazione minima rispetto a ciò che ha scritto M1n021.

C++:
#include <iostream>
using namespace std;
int main()
{
    int m[3][3] = {{1, 2, 3},
                   {4, 5, 6},
                   {7, 8, 9}};

    for(unsigned int i = 0; i < 3 * 3 && *(*m + i); ++i)
    {
        cout << i << endl;
    }
}

Ho solo sostituito [i].

Capisco l'undefined behavior... ma è un tantino aleatorio così. 😅 Ci si ritrova a non poter ottimizzare del codice poichè non si sa che cosa succede. Sarebbe meglio evitare di fargli spaccare il codice, piuttosto evitare l'ottimizzazione di alcune parti quando ci sono questi "edge case".
Per altro si verifica con GCC/G++, gli altri a quanto sembra funzionano come ci si aspetterebbe.
 
  • Mi piace
Reazioni: M1n021

M1n021

Nuovo Utente
143
68
Capisco l'undefined behavior... ma è un tantino aleatorio così. 😅 Ci si ritrova a non poter ottimizzare del codice poichè non si sa che cosa succede. Sarebbe meglio evitare di fargli spaccare il codice, piuttosto evitare l'ottimizzazione di alcune parti quando ci sono questi "edge case".
Ciò riassume perfettamente il mio pensiero.

Dai, in fin dei conti ne è uscita una discussione piuttosto interessante! 🙂


Per quanto riguarda il codice che stavo implementando, visto che l'array multidimensionale incriminato è membro di una classe, alla fine ho risolto seguendo il suggerimento iniziale di @bigendian aggiungendo alla classe un membro puntatore p che punta al primo elemento del suddetto array multidimensionale; in tal modo ogni volta che devo scorrere l'array multidimensionale alla stregua di un array monodimensionale mi basta utilizzare p, evitando quindi di dover dichiarare un puntatore volta per volta.

Non ho abbandonato l'idea di installare un nuovo compilatore su codeblocks, ma la faccenda si è rivelata più complicata di quello che mi aspettavo; ne approfitto comunque per ringraziare @DispatchCode e @BrutPitt per i consigli che mi hanno dato al riguardo.
 
  • Mi piace
Reazioni: DispatchCode

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,208
1,845
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Ciò riassume perfettamente il mio pensiero.

Dai, in fin dei conti ne è uscita una discussione piuttosto interessante! 🙂
Concordo, topic come questi sono sempre i benvenuti. 😉

Non ho abbandonato l'idea di installare un nuovo compilatore su codeblocks, ma la faccenda si è rivelata più complicata di quello che mi aspettavo; ne approfitto comunque per ringraziare @DispatchCode e @BrutPitt per i consigli che mi hanno dato al riguardo.

Di nulla. Mah guarda, puoi anche scaricare Visual Studio che è comunque free. Ha come default il suo compilatore, MSVC, ma volendo sempre dalle impostazioni puoi modificarlo con il path a GCC o Clang.
 

bigendian

Utente Attivo
718
410
OS
Linux
E' stata una discussione interessante.

Inutile invocare Rust per poter sbagliare meglio, o colpevolizzare il compilatore se si programma male.

Accedendo a *m[3] si esce dall'array.


@M1n021
perche non lavorare con l'editor che preferisci, e compilare con semplici makefile, (che per un solo file neanche servono), da riga di comando, cosi da possedere/controllare tutti i flag di compilazione utilizzati ? Oppure, se pensi che l'IDE ti dia un valore aggiunto, hai Atom, QtCreator VSCodium etc, anche code blocks non male
 
  • Mi piace
Reazioni: BAT e Andretti60

BrutPitt

Utente Attivo
1,166
1,262
Per quanto riguarda il codice che stavo implementando, visto che l'array multidimensionale incriminato è membro di una classe, alla fine ho risolto seguendo il suggerimento iniziale di @bigendian aggiungendo alla classe un membro puntatore p che punta al primo elemento del suddetto array multidimensionale; in tal modo ogni volta che devo scorrere l'array multidimensionale alla stregua di un array monodimensionale mi basta utilizzare p, evitando quindi di dover dichiarare un puntatore volta per volta.
Tornando al codice... permettimi di dire (senza alcuna critica, ovviamente) che effettivamente sembrava piu' il codice di un "programmatore C" che sta implementando il C++.

Non so a cosa ti servira', per cui magari e' prematuro per me affermarlo, ma credo la dichiarazione migliore in C++ possa essere questa:
C++:
vector<A> m {{false, {2, 8, 5}}, {true,  {}},        {false, {1}},
                 {true,  {}       }, {false, {2, 8, 5}}, {false, {11, 18}},
                 {true,  {}       }, {true,  {}},        {false, {1, 5, 2, 8, 5}}};
(o ventualmente l'utilizzo di altro container)

A quel punto (visto che ami i puntatori 😅 ) potresti anche eliminare gli indici e utilizzare direttamente il puntatore o il riferimento all'elemento, con un ciclo for del tipo:

C++:
for (vector<A>::iterator a = m.begin() ; a != m.end(); ++a) 
//for (auto a = m.begin() ; a != m.end(); ++a)  ... e' equivalemte
{
      if(!(a->flag || a->v.size())) {
           // faccio qualcosa passando "a"
        break;
     } else  cout << a->flag << endl;
}

// che equivale a ...
for (A &a : m)   {
      if(!(a.flag || a.v.size())) {
           // faccio qualcosa passando "a"
          break;
    }
}
// o anche
for(auto a : m)

Ovviamente voleva essere solo un modo per darti altre "prospettive"

Non ho abbandonato l'idea di installare un nuovo compilatore su codeblocks, ma la faccenda si è rivelata più complicata di quello che mi aspettavo; ne approfitto comunque per ringraziare @DispatchCode e @BrutPitt per i consigli che mi hanno dato al riguardo.
Se ci dici quale sia l'ostacolo magari vediamo di scavalcarlo 😉
 
Ultima modifica:

M1n021

Nuovo Utente
143
68
Tornando al codice... permettimi di dire (senza alcuna critica, ovviamente) che effettivamente sembrava piu' il codice di un "programmatore C" che sta implementando il C++.

Non so a cosa ti servira', per cui magari e' prematuro per me affermarlo, ma credo la dichiarazione migliore in C++ possa essere questa: ...
Il punto è che programmando così per hobby, e non avendo alcun background informatico in senso stretto, non do molta importanza al fatto che il codice che sto scrivendo possa essere considerato C style o C++ style, peraltro nemmeno so quale sia precisamente la linea di demarcazione che separa l'uno dall'altro.
Quando possibile utilizzo il C, ma se mi servono alcune funzionalità messe a disposizione dal C++ (per esempio OOP, template, overloading, o anche classi come std::string e std::vector per evitare di reinventare la ruota), allora utilizzo quest'ultimo. Ma, anche quando programmo in C++, se una collezione di oggetti possiede una dimensione fissa, allora preferisco ricorrere ad un array piuttosto che ad un vector, magari sbaglio, ma, oltre al fatto che lo ritengo più esplicativo, è soprattutto per una questione di abitudine! 😅


A quel punto (visto che ami i puntatori 😅 ) potresti anche eliminare gli indici e utilizzare direttamente il puntatore o il riferimento all'elemento, con un ciclo for del tipo:
...
Ovviamente voleva essere solo un modo per darti altre "prospettive"
Figurati lo apprezzo, non ti preoccupare. Comunque spesso utilizzo anche direttamente puntatori e riferimenti (meno gli iteratori, sempre per una questione di abitudine), molto dipende dal contesto e forse anche dall'ispirazione del momento! 😅


Se ci dici quale sia l'ostacolo magari vediamo di scavalcarlo 😉
Nessuno ostacolo in particolare, è solo che non ho molta confidenza col "dietro le quinte della programmazione" e mi sono reso conto che esistono tante versioni e questioni di compatibilità che credo richiedano un minimo di approfondimento in più da parte mia (ovviamente mi riferisco all'installazione di un nuovo compilatore e non all'installazione di un IDE con compilatore integrato).
Ti ringrazio comunque per la disponibilità e vi prometto che se incontro qualche difficoltà tornerò a rompervi le scatole! 😂
 

bigendian

Utente Attivo
718
410
OS
Linux
Il punto è che programmando così per hobby, e non avendo alcun background informatico in senso stretto, non do molta importanza al fatto che il codice che sto scrivendo possa essere considerato C style o C++ style, peraltro nemmeno so quale sia precisamente la linea di demarcazione che separa l'uno dall'altro.
Non ci sono divieti nella programmazione C++, usato un array bidimensionale piu di qualche volta, personalmente mi fermo e pondero molto bene cosa utilizzare, considero tutto quel che e' lecito a seconda di quello che devo fare, ma ad una condizione fondamentale, che si sappia quello che si fa, e ci si protegga in maniera adeguata nel caso.

Utilizzare un vector rispetto a un array semplice e' quasi sempre conveniente, l'overhead rispetto a un array e' minimo, e nel tuo caso, il vector ti avrebbe tutelato e facilitato.

Ma e' fondamentale utilizzare oggetti e template STL che si conoscano, che siano veramente "tuoi", capiti.

Quando invece si utilizza codice preso da altre parti senza capirne il motivo, si entra nel "cargo cult".
 
Stato
Discussione chiusa ad ulteriori risposte.

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!