Motivo dell'operatore di incremento (post / pre) in Java o C #

8

Recentemente, mi sono imbattuto in domande sulla previsione dell'output di codice che utilizza pesantemente gli operatori post / pre incremento su interi. Sono un programmatore C esperto, quindi mi sono sentito come a casa, ma le persone hanno fatto affermazioni che Java ha copiato ciecamente da C (o C ++) e che questa è una funzionalità inutile in Java.

Detto questo, non sono in grado di trovare una buona ragione per questo (specialmente tenendo a mente la differenza tra i post / formulari) in Java (o C #), perché non è come se manipolassero gli array e li usassero come stringhe in Java. Inoltre, è passato molto tempo fa quando ho cercato per ultimo il bytecode, quindi non so se c'è un'operazione di INC , ma non vedo alcun motivo per cui questo

for(int i = 0; i < n; i += 1)

potrebbe essere meno efficace di

for(int i = 0; i < n; i++)

C'è qualche parte particolare della lingua in cui questo è veramente utile, o questa è solo una funzione per portare i programmatori C in città?

    
posta Nemanja Boric 24.03.2014 - 12:32
fonte

5 risposte

19

is this just a feature to bring C programmers in town

È sicuramente una caratteristica "portare programmatori C (o C ++) in città", ma usare la parola "solo" qui sottovaluta il valore di tale somiglianza.

  • rende il codice (o almeno i frammenti di codice) più facile da trasferire da C (o C ++) a Java o C #

  • i++ è meno da digitare di i += 1 e x[i++]=0; è molto più idiomatico di x[i]=0;i+=1;

E sì, il codice che utilizza pesantemente gli operatori di post-pre-incremento può essere difficile da leggere e gestire, ma per qualsiasi codice in cui tali operatori vengono utilizzati in modo improprio, non mi aspetto un drastico aumento della qualità del codice anche quando la lingua non fornisce questi operatori. Questo perché se hai sviluppatori che non si curano della manutenibilità, troveranno sempre dei modi per scrivere codice difficile da capire.

Correlati: C'è qualche differenza tra Java e gli operatori C ++? Da questa risposta si può dedurre che qualsiasi comportamento dell'operatore ben definito in C è simile in Java e Java aggiunge solo alcune definizioni per la precedenza degli operatori in cui C ha un comportamento non definito. Non sembra una coincidenza, sembra piuttosto intenzionale.

    
risposta data 24.03.2014 - 13:28
fonte
6

Uso a volte l'incremento postfisso nelle dichiarazioni di ritorno. Per esempio. considera questo:

//Java
public class ArrayIterator implements Iterator<T> {
   private final T[] array;
   private int index = 0; 
   public ArrayIterator(T ... array) {
      this.array = array;
   }

   public T next {
      if (! hasNext()) throw new NoSuchElementException();
      return array[index++];   
   }
   ...
}

Non puoi farlo con index += 1 . Quindi almeno la versione postfix può salvarti di tanto in tanto alcune righe.

Detto questo, questi operatori non sono davvero necessari e potrebbero confondere le persone. So che Scala ha deciso contro questi operatori (hai solo += e -= , come hai suggerito) e, a causa dell'approccio più "di alto livello", in realtà non mi mancano. Spero che Java si sviluppi (più lentamente) nella stessa direzione.

Tuttavia Java ha un sacco di altri operatori che non vedi molto spesso "in the wild" (hai mai usato ^= o >>>= ?), e a nessuno importa.

    
risposta data 24.03.2014 - 13:04
fonte
4

Ho costruito molte lingue nel corso degli anni, principalmente per scopi speciali. Quello che succede è che hai un vasto pubblico e tutti hanno aspettative. Nel considerare ciascuna funzionalità, è necessario valutare il vantaggio della funzionalità rispetto al costo di eventuali violazioni delle aspettative.

Uno di quelli che ho dovuto eseguire a ritroso era la divisione intera, che normalmente tronca verso il basso, giusto? Come 3 / 2 = 1.5 = 1 , giusto? Bene, ai tempi di Fortran, qualcuno ha deciso -3 / 2 = -1.5 = -1 (non -2). In altre parole, se il dividendo è negativo e il divisore è positivo, dovrebbe troncare su . Nota che cosa questo implica - in quel caso il resto è negativo . Ciò viola il consueto presupposto che resto = modulo. Se stai facendo grafica, con coordinate intere, questo può portare a tutti i tipi di problemi. SO, nel linguaggio ho semplicemente avuto la divisione intera troncare verso il basso tutti il tempo, e dirlo nel doc.

E COSÌ, indovina cos'è successo? Tutto si è scatenato. La lingua aveva un bug nella divisione intera!

Non ha funzionato dire che il vecchio sistema era rotto. È stato più facile cambiarlo che sostenerlo.

Quindi per rispondere alla tua domanda, in linguaggi come C # e Java, è semplicemente più facile includere gli operatori ++ (che personalmente mi piacciono) piuttosto che spiegare perché no.

    
risposta data 24.03.2014 - 13:57
fonte
2

Sì, non è niente di importante in sé, il suo unico vantaggio è lo zucchero sintattico che rende più facile la scrittura.

La ragione per cui è in C in primo luogo è solo perché il PDP-11 che era la base per C, ai vecchi tempi, aveva un'istruzione speciale per incrementare di 1. In quei giorni, usando questa istruzione era importante ottenere più velocità dal sistema, da qui la funzionalità del linguaggio.

Tuttavia, penso che alla gente piaccia il comando così tanto che si lamenterebbero se non ci fosse.

    
risposta data 24.03.2014 - 17:30
fonte
2

Questa è sintassi idiomatica in C per molte situazioni (come il ciclo for che hai citato), così come altri hanno detto, può aiutare coloro che passano a Java come nuovo linguaggio e facilita il porting preesistente Codice in stile C. Per questi motivi, è stata una decisione naturale da prendere nei primi tempi di Java per accelerare l'adozione della nuova lingua. Ha meno senso ora, perché il codice più compatto viene a scapito di richiedere ai programmatori di imparare la sintassi che non è strettamente necessaria.

Coloro a cui piace trovano comodo e naturale. Fare a meno sembra imbarazzante. Usarlo non guadagna efficienza, è una questione di leggibilità. Se ritieni che i tuoi programmi siano più facili da leggere e gestire utilizzando questi operatori, usali.

Il senso originale in C era più che "aggiungi 1" o "sottrai 1". È molto più dello zucchero sintattico o dei piccoli guadagni in termini di prestazioni. L'operatore in C significa "incremento (o decremento) all'elemento successivo". Se hai un puntatore a qualcosa di più grande di un byte, e passi al prossimo indirizzo come in *pointer++ , l'incremento effettivo potrebbe essere di 4, o 8, o qualsiasi cosa sia richiesta. Il compilatore fa il lavoro per te, tenendo traccia delle dimensioni degli elementi di dati e saltando il giusto numero di byte:

int k;
int *kpointer = &k;
*kpointer++ = 7;

Sulla mia macchina, questo aggiunge 4 a kpointer, non aggiunge 1. Questo è un vero aiuto in C, evitando errori e salvando invocazioni spurie di sizeof (). Non c'è aritmetica puntatore equivalente in Java, quindi questa non è una considerazione. Lì, si tratta più della potenza dell'espressione che di qualsiasi altra cosa.

    
risposta data 22.02.2018 - 03:21
fonte

Leggi altre domande sui tag