Errore invalid operands of types float and double to binary operator

di il
50 risposte

50 Risposte - Pagina 3

  • Re: Errore invalid operands of types float and double to binary operator

    Nippolo ha scritto:


    Mi riferivo invece a qualcosa del genere:
    int n;
    cin >> n;
    funzione(n);
    In 3 linee ovviamente non serve, siamo sempre lì.

    Ma in un programma molto più grande (anche se non milioni di linee, ma migliaia), c'è sempre la possibilità che qualcuno introduca delle modifiche, magari con una

    if(n>0) ... salta l'input ...

    o chissà cosa. Tieni presente che la modifica viene fatta da un altro programmatore, su un file sorgente in cui non vedi la dichiarazione della variabile che magari sta in un altro file tra i tanti file sorgenti.

    Se la n non è inizializzata, può sorgere qualche imprevisto e la modifica può introdurre un effetto non voluto.
  • Re: Errore invalid operands of types float and double to binary operator

    oregon ha scritto:


    Un buffer overflow senza altre conseguenze
    Senza altre conseguenze??? Cioè, la perdita del controllo su un'applicazione non è nemmeno una "conseguenza" per te...?

    Nippolo ha scritto:


    con quale criterio dovrei scegliere il valore con cui inizializzare n?
    Con il valore che ti serve nel momento quando utilizzi la variabile per la prima volta. Proprio per questo la regola "sempre inizializzare" ha poco senso: Se non sai nemmeno quale valore ti serve, allora perché metterci un valore qualsiasi, zero o -1 o 12345? Per evitare la warning "using uninitialised variable" del compilatore?? Un ottimo modo per introdurre dei bugs...

    oregon ha scritto:


    su un file sorgente in cui non vedi la dichiarazione della variabile che magari sta in un altro file tra i tanti file sorgenti.
    Una variabile locale inizializzata in un altro file... interessante. Ti è già capitato in pratica?
  • Re: Errore invalid operands of types float and double to binary operator

    In quel caso non parlavo di variabili locali, ovviamente. Per le locali vale la questione se inizializzate in altra parte del file abbastanza lontano dal suo uso. E anche se per ipotesi un valore vale l'altro, conoscere quale sia quello iniziale aiuta nel debugging.

    Per l'overflow pensavo non ti si dovesse spiegare la differenza tra le due problematiche in ipotesi, un crash (sebbene sia un problema) non è paragonabile ad un problema di sicurezza introdotto e che vale per quel sw, quel sistema e magari altri sistemi dell'infrastruttura.
  • Re: Errore invalid operands of types float and double to binary operator

    Nippolo ha scritto:


    Mi riferivo invece a qualcosa del genere:
    int n;
    cin >> n;
    funzione(n);
    Ok che è buona pratica inizializzare le variabili, ma con quale criterio dovrei scegliere il valore con cui inizializzare n?
    Generalmente, come sopra accennato, in questi casi, a zero.
    Però sono 3 righe.
    Vediamo un esempio sempre banale, ma leggermente meno immediato
    
    int Decoder::skip() {
      int c; /// qui cosa metteresti?
      if (pr.isModeled()) {
        while (curr==0)
          curr=get();
        while (curr && (c=get())>=0) 
          curr=curr<<8|c;
        while ((c=get())==0) ; 
        return c;
      }
      else {
        if (curr==0)  
          for (int i=0; i<4 && (c=get())>=0; ++i) curr=curr<<8|c;
        while (curr>0) {
          while (curr>0) {
            --curr;
            if (get()<0) return error("skipped to EOF"), -1;
          }
          for (int i=0; i<4 && (c=get())>=0; ++i) curr=curr<<8|c;
        }
        if (c>=0) c=get();
        return c;
      }
    }
    
  • Re: Errore invalid operands of types float and double to binary operator

    E se invece ti mettessi questo
    Come definiresti ncomp?
      if (v[0]=='c') {
          while (v.size()<3) v.push_back(0);
          comp+=itos(ncomp)+" ";
          sb=11;  // count context bits
          if (v[2]<256) sb+=lg(v[2]);
          else sb+=6;
          for (unsigned i=3; i<v.size(); ++i)
            if (v[i]<512) sb+=nbits(v[i])*3/4;
          if (sb>membits) sb=membits;
          if (v[1]%1000==0) comp+="icm "+itos(sb-6-v[1]/1000)+"\n";
          else comp+="cm "+itos(sb-2-v[1]/1000)+" "+itos(v[1]%1000-1)+"\n";
    
          // special contexts
          hcomp+="d= "+itos(ncomp)+" *d=0\n";
          if (v[2]>1 && v[2]<=255) {  // periodic context
            if (lg(v[2])!=lg(v[2]-1))
              hcomp+="a=c a&= "+itos(v[2]-1)+" hashd\n";
            else
              hcomp+="a=c a%= "+itos(v[2])+" hashd\n";
          }
          else if (v[2]>=1000 && v[2]<=1255)  // distance context
            hcomp+="a= 255 a+= "+itos(v[2]-1000)+
                   " d=a a=*d a-=c a> 255 if a= 255 endif d= "+
                   itos(ncomp)+" hashd\n";
    
          // Masked context
          for (unsigned i=3; i<v.size(); ++i) {
            if (i==3) hcomp+="b=c ";
            if (v[i]==255)
              hcomp+="a=*b hashd\n";  // ordinary byte
            else if (v[i]>0 && v[i]<255)
              hcomp+="a=*b a&= "+itos(v[i])+" hashd\n";  // masked byte
            else if (v[i]>=256 && v[i]<512) { // lz77 state or masked literal byte
              hcomp+=
              "a=r 1 a> 1 if\n"  // expect literal or offset
              "  a=r 2 a< 64 if\n"  // expect literal
              "    a=*b ";
              if (v[i]<511) hcomp+="a&= "+itos(v[i]-256);
              hcomp+=" hashd\n"
              "  else\n"  // expect match offset byte
              "    a>>= 6 hashd a=r 1 hashd\n"
              "  endif\n"
              "else\n"  // expect new code
              "  a= 255 hashd a=r 2 hashd\n"
              "endif\n";
            }
            else if (v[i]>=1256)  // skip v[i]-1000 bytes
              hcomp+="a= "+itos(((v[i]-1000)>>8)&255)+" a<<= 8 a+= "
                   +itos((v[i]-1000)&255)+
              " a+=b b=a\n";
            else if (v[i]>1000)
              hcomp+="a= "+itos(v[i]-1000)+" a+=b b=a\n";
            if (v[i]<512 && i<v.size()-1)
              hcomp+="b++ ";
          }
          ++ncomp;
        }
  • Re: Errore invalid operands of types float and double to binary operator

    jj2007 ha scritto:


    ...Proprio per questo la regola "sempre inizializzare" ha poco senso: Se non sai nemmeno quale valore ti serve, allora perché metterci un valore qualsiasi, zero o -1 o 12345?
    Banalmente per la ripetibilità, ovvero un comportamento il più possibile deterministico.
    Ci sono poche situazioni (elemento già sopra indicato da altri) più difficili del "bug fantasma", ovvero di un funzionamento che TU ritieni deterministico, ma che in realtà non lo è.

    Lo stesso programma sul MIO computer ha un comportamento, sul TUO uno diverso.

    Non importa se giusto o sbagliato, può essere diverso. E, talvolta, può essere difficilissimo o perfino impossibile fare il debug sul TUO (ad esempio perchè è un dispositivo wifi montato in cima a una montagna).

    Nella storia ci sono bug di questo genere che hanno richiesto addirittura anni, da parte di team di decine di ingegneri del software, per essere finalmente individuati.

    Solo chi non ha la minima idea del "mondo reale" (dell'informatica) può non esserne "terrorizzato" e fare tutto quanto possibile per ridurre (non eliminare) i rischi.
  • Re: Errore invalid operands of types float and double to binary operator

    jj2007 ha scritto:


    oregon ha scritto:


    Un buffer overflow senza altre conseguenze
    Senza altre conseguenze??? Cioè, la perdita del controllo su un'applicazione non è nemmeno una "conseguenza" per te...?

    Nippolo ha scritto:


    con quale criterio dovrei scegliere il valore con cui inizializzare n?
    Con il valore che ti serve nel momento quando utilizzi la variabile per la prima volta. Proprio per questo la regola "sempre inizializzare" ha poco senso: Se non sai nemmeno quale valore ti serve, allora perché metterci un valore qualsiasi, zero o -1 o 12345? Per evitare la warning "using uninitialised variable" del compilatore?? Un ottimo modo per introdurre dei bugs...

    oregon ha scritto:


    su un file sorgente in cui non vedi la dichiarazione della variabile che magari sta in un altro file tra i tanti file sorgenti.
    Una variabile locale inizializzata in un altro file... interessante. Ti è già capitato in pratica?
    Secondo me hai anche interpretato male la regola "sempre inizializzare". Non è stato detto che per ogni variabile creata bisogna fare una roba del tipo int a = 0; e ci mancherebbe che fosse così...
    Però molto spesso è una buona pratica, prendiamo ad esempio questa funzione, proviene dal kernel Linux:
    
    static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
    {
    	acpi_status status = AE_OK;
    	unsigned long long tmp;
    
    	if (!tz)
    		return -EINVAL;
    
    	tz->last_temperature = tz->temperature;
    
    	status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
    	if (ACPI_FAILURE(status))
    		return -ENODEV;
    
    	tz->temperature = tmp;
    	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
    			  tz->temperature));
    
    	return 0;
    }
    Ora al di là del codice che è anche semplice da seguire, nota come la variabile status venga inizializzata anche se nelle righe successive in realtà assume il valore restituito dalla funzione acpi_evaluate_integer, che riporto qui sotto insieme alla definizione del tipo acpi_status se può aiutare perché è anch'esso di facile comprensione.
    Secondo te perché quella variabile viene comunque inizializzata ed invece tmp no? Stando al tuo ragionamento sarebbe inutile perché non sai a priori che valore deve assumere.
    
    /*
     * acpi_status should return ACPI specific error codes, not BeOS ones.
     */
    typedef uint32 acpi_status;
    
    
    acpi_status acpi_evaluate_integer(acpi_handle handle,
    		      acpi_string pathname,
    		      struct acpi_object_list *arguments, unsigned long long *data)
    {
    	acpi_status status = AE_OK;
    	union acpi_object element;
    	struct acpi_buffer buffer = { 0, NULL };
    
    	if (!data)
    		return AE_BAD_PARAMETER;
    
    	buffer.length = sizeof(union acpi_object);
    	buffer.pointer = &element;
    	status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
    	if (ACPI_FAILURE(status)) {
    		acpi_util_eval_error(handle, pathname, status);
    		return status;
    	}
    
    	if (element.type != ACPI_TYPE_INTEGER) {
    		acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
    		return AE_BAD_DATA;
    	}
    
    	*data = element.integer.value;
    
    	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
    
    	return AE_OK;
    }
  • Re: Errore invalid operands of types float and double to binary operator

    Riporto un pezzo di uno dei miei primi post in questo topic:
    Da dove nasce quindi l'utilità di inizializzare tutte le variabili? Non so, magari un'inizializzazione strategica potrebbe rivelarsi utile in fase di debugging?
    Alla luce di quanto letto negli ultimi post credo sarebbe bastato un si.

    @+m2+

    Scusa ma non conoscendo il contesto di quelle porzioni di codice e molte delle funzioni utilizzate, ammesso che i dati in mio possesso siano sufficienti per poter rispondere, proprio non mi va di scervellarmi e di mettermi a studiare argomenti che non conosco.

    P.S.
    Ho trovato molto utile e chiaro il tuo intervento sulla ripetibilità.
    Secondo me hai anche interpretato male la regola "sempre inizializzare". Non è stato detto che per ogni variabile creata bisogna fare una roba del tipo int a = 0; e ci mancherebbe che fosse così...
    Anche io l'ho interpretata così.
    In ogni caso attendo che venga fatta luce sulla questione da te posta, magari mi chiarirà ulteriormente le idee.
  • Re: Errore invalid operands of types float and double to binary operator

    Non c'è contesto da conoscere sono esempi banali. Comunque giusto per mostrare come già poche decine di righe rendono la cosa non banale, addirittura richiede 'scervellarsi' (ovviamente per modo di dire).
    immagina su 1 milione o più.
  • Re: Errore invalid operands of types float and double to binary operator

    Non essendo del campo non ti so dire se sono davvero esempi così banali oppure tu stia esagerando un po', in ogni caso dopo un'occhiata veloce, non conoscendo: contesto, significato di alcune variabili (per alcune delle quali manca anche la dichiarazione), alcune funzioni e costrutti... ho realizzato che non mi va di mettermi a studiare solo per cercare di capire un esempio.
    D'altra parte mi sembra ovvio che (in linea di massima) il numero di righe sia direttamente proporzionale alla "complessità" del codice e alla probabilità di commettere errori, mi pare che nessuno l'abbia messo in dubbio.
  • Re: Errore invalid operands of types float and double to binary operator

    IfNotFalseTrue ha scritto:


    Però molto spesso è una buona pratica, prendiamo ad esempio questa funzione, proviene dal kernel Linux:
    
    static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
    {
    	acpi_status status = AE_OK;
    Ora al di là del codice che è anche semplice da seguire, nota come la variabile status venga inizializzata
    Questo thread tratta la questione se inizializzare variabili locali, visto il rischio che vengano utilizzate con il loro contenuto originale, cioè la spazzatura che di solito si trova nello stack frame. E ci sono due posizioni:

    1. Gli esperti dicono che bisogna sempre inizializzare, quindi int tmp=0;
    2. I dilettanti (=io) dicono che è compito del compilatore segnalare se una variabile locale viene utilizzata senza essere inizializzata.

    Nel tuo caso, la variabile è globale e quindi contiene quello che altre parti del programma ci hanno messo dentro. Visto che è un valore "status", ha ovviamento un senso metterci un valore default, ma questo è un altro tema.

    P.S.: Già che ci siamo, ecco uno sguardo al livello più "sotto"...
    static long long foo(void)
    {
       int mylocal = 123;
       unsigned long long tmp;
    
       return 0x12345678;
    }
    Ed ecco come GCC traduce questa funzione:
    Address             Hex dump                 Command                           Comments
    00401340            Ú$  55                   push ebp                          ; entry a foo
    00401341            ³.  89E5                 mov ebp, esp                      ; crea stack frame
    00401343            ³.  83EC 10              sub esp, 10                       ; crea variabili locali mylocal e tmp
    00401346            ³.  C745 FC 7B000000     mov dword ptr [ebp-4], 7B         ; metti 123 in mylocal
    0040134D            ³.  B8 78563412          mov eax, 12345678                 ; lo dword retval
    00401352            ³.  BA 00000000          mov edx, 0                        ; hi dword
    00401357            ³.  C9                   leave
    00401358            À.  C3                   retn
    Nessun codice per tmp, ma assegnare 123 a mylocal costa inutilmente 7 bytes. Se lo fai per un milione di righe, allora hai una spiegazione perché troviamo sempre più bloatware sui nostri pc (ovviamente gli esperti ci diranno che RAM non costa niente, e che cercare performance hit instruction cache su Google è solo uno spreco di tempo prezioso).
  • Re: Errore invalid operands of types float and double to binary operator

    Nippolo ha scritto:


    Non essendo del campo non ti so dire se sono davvero esempi così banali...
    bhè se scrivo che sono banali significa che lo sono ontologicamente
    ...Se lo fai per un milione di righe, allora hai una spiegazione perché troviamo sempre più bloatware sui nostri pc (ovviamente gli esperti ci diranno che RAM non costa niente, e che cercare performance hit instruction cache su Google è solo uno spreco di tempo prezioso).
    Eccolo l'esperto.
    No, bloatware non c'entra nulla in questo contesto.
    Nè l'utilizzo della RAM.
    Nè la cache.

    Sono approcci da (nel senso proprio del termine) ignoranti, ovvero ignorare come funziona una macchina moderna, ed i programmi moderni.
    Ovviamente bisognarebbe anche sapere come funzionavano le macchine vecchie, e i programmi vecchi, per comprenderne differenze ed accorgimenti.

    Aspettarsi di delegare a "qualcuno" (il compilatore? sto ridendo) "qualcosa" significa banalmente perderne il controllo.
    Tra l'altro cosa sia, e come funzioni, un compilatore "oggi" è un altro argomento titanico.

    Versione breve: non sei convinto? Vuoi fare come ti pare?
    Fallo pure, per me (e quelli come me) rappresenti un "concorrente" in meno
  • Re: Errore invalid operands of types float and double to binary operator

    Carissimo m2, se ti mancano gli argomenti, passi sempre agli insulti?
  • Re: Errore invalid operands of types float and double to binary operator

    jj2007 ha scritto:


    IfNotFalseTrue ha scritto:


    Però molto spesso è una buona pratica, prendiamo ad esempio questa funzione, proviene dal kernel Linux:
    
    static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
    {
    	acpi_status status = AE_OK;
    Ora al di là del codice che è anche semplice da seguire, nota come la variabile status venga inizializzata
    Questo thread tratta la questione se inizializzare variabili locali, visto il rischio che vengano utilizzate con il loro contenuto originale, cioè la spazzatura che di solito si trova nello stack frame. E ci sono due posizioni:

    1. Gli esperti dicono che bisogna sempre inizializzare, quindi int tmp=0;
    2. I dilettanti (=io) dicono che è compito del compilatore segnalare se una variabile locale viene utilizzata senza essere inizializzata.

    Nel tuo caso, la variabile è globale e quindi contiene quello che altre parti del programma ci hanno messo dentro. Visto che è un valore "status", ha ovviamento un senso metterci un valore default, ma questo è un altro tema.
    Come fa una variabile che viene dichiarata dentro una funzione ad essere definita come globale? Io quel tipo di variabili le ho sempre chiamate locali perché appunto esistono solo in quella funzione lì.
  • Re: Errore invalid operands of types float and double to binary operator

    Ups, hai ragione! Avevo letto male, infatti è locale. Le mie scuse.

    Ciò non toglie, però, che non serve inizializzare la variabile locale status, perché viene utilizzata solo dopo questa riga:
    status = acpi_evaluate_object(...)
Devi accedere o registrarti per scrivere nel forum
50 risposte