I, j = 1 è davvero fuorviante? [chiuso]


11

C'è un argomento comune sull'inizializzazione di variabili multiple in una riga, ovvero:

Consideriamo ad esempio int i, j = 1; che potrebbe indurre alcune persone a credere erroneamente che entrambe le variabili vengano inizializzate

Potremmo sostenere che qualcuno dovrebbe conoscere abbastanza la sintassi della sua lingua per non sbagliarci. Un altro argomento potrebbe essere come sviluppatori impariamo così tante lingue che possiamo commettere errori tra le specificità tra le lingue.

Tuttavia, per quel caso molto specifico, mi chiedo che esista un linguaggio in cui la stessa sintassi i, j = 1 inizializza entrambe le variabili?

In caso contrario, tale argomento non si applica.


2
Se la tua lingua è sana, la potenziale confusione è innocua perché l'accesso a una variabile non inizializzata provoca un errore del compilatore.
CodesInChaos

4
@CodesInChaos stai dicendo che C non è sano?
Baldrickk,

2
Solo perché una lingua permette qualcosa non significa che non stai causando dolore inutile agli umani. L'unico posto in cui viene richiesto questo codice è durante i quiz progettati per punire coloro che non hanno memorizzato le specifiche della lingua. Ho sempre fallito questo tipo di domande. Bleh.
candied_orange

2
In Visual Basic 6 Dim Apple, Orange, Pear as Fruitè una dichiarazione legale. Supponi di non conoscere VB. La tua prima impressione Appleè di tipo Fruit? Non è. Ricorda, le lingue sono spesso lette da persone che non sono esperte in quella lingua; se sei un esperto, usa saggiamente la lingua per comunicare chiaramente le tue intenzioni anche ai non esperti. Non utilizzo mai più inizializzazioni in nessuna lingua.
Eric Lippert,

13
Allo stesso modo: considera var x = 1, y = 1.5; È lo stesso di int x = 1; double y = 1.5;o è lo stesso di double x = 1, y = 1.5;? Quando abbiamo aggiunto vara C # 3.0 ho fatto un sondaggio e ho scoperto che circa la metà delle persone credeva che la prima fosse "ovviamente" corretta e l'altra metà credeva che l'altra fosse "ovviamente" corretta, e quindi l'abbiamo resa illegale. Una caratteristica che induce in errore la metà della popolazione è una caratteristica negativa.
Eric Lippert,

Risposte:


37

Penso di no, ma non è questo il punto. Il punto è che i, j = 0è molto facilmente scambiato per i = j = 0, che fa initialize entrambi. La chiarezza è il requisito più importante per il codice sorgente accanto alla correttezza e il fatto che questa domanda si ponga dimostra che la chiarezza non è ottimale.


3
Direi anche che se tale affermazione non inizializza entrambe le affermazioni, perché esiste?
Berin Loritsch,

2
@BerinLoritsch dipende dalla lingua. Questo è spesso fatto in JavaScript a causa del sollevamento delle dichiarazioni: molti considerano le migliori pratiche dichiarare le variabili in cima all'ambito in cui sono disponibili anche se non le inizializzate fino allo spot usato nel codice . Quasi tutti gli strumenti di trasformazione del codice vengono generati in questo modo.
Jared Smith,

1
Suppongo sia una cosa se uno strumento di output del codice lo facesse, dal momento che si suppone che sia attendibile. Tuttavia, per gli umani raccomanderei di non combinare la dichiarazione e l'inizializzazione dell'ultimo elemento solo su una riga. Sembra solo un bug in attesa di accadere.
Berin Loritsch,

2
@JaredSmith Oltre a Maple, non riesco a pensare a una lingua in cui questo è attualmente desiderato, anche C ora preferisce avvicinarsi all'ambito (come C ++ e la maggior parte delle altre lingue con compilatori statici decenti) perché offre il vantaggio di arrestare potenziali bug e consente il compilatore per decidere cosa fare della variabile purché la funzionalità non cambi, consentendo potenzialmente migliori ottimizzazioni dato che potresti cavartela con meno registri.
quando

6
Indipendentemente dalla lingua, ci si dovrebbe chiedere "Qual è il vantaggio della scrittura int i, j=1rispetto int i; int j = 1(o meglio, linee separate)?"
Chepner,

2

Penso che puoi discutere per entrambe le parti:

  • Kontra i, j = 0: I
    matematici usano questo per indicare che entrambi ie jdovrebbero essere zero.

  • Pro i, j = 0:
    si tratta semplicemente di conoscere la precedenza dei tuoi operatori. E se hai dei dubbi sulla loro precedenza, ora è il momento di cercarlo.

    È lo stesso motivo per cui scriviamo cose come a.b += c[i]*d[i];senza le parentesi. Naturalmente questo equivale a (a.b) += ((c[i])*(d[i]));, ma ci si può aspettare che i programmatori conoscano a memoria la precedenza degli operatori più utilizzati e siano in grado di cercare la precedenza degli operatori quando non sono sicuri. Pertanto, le parentesi sono generalmente considerate disordine inutile a meno che non forzino un ordine di valutazione diverso da quello prescritto dalla precedenza dell'operatore.

    Certo, ci sono eccezioni. In entrambi i casi la precedenza di <<e +è generalmente considerata abbastanza ambigua da mettere in guardia le parentesi. Ma questa è l'eccezione che dimostra la regola.

Io, per esempio, cadrei di più sul lato Pro, ma sono pronto a attenermi a qualsiasi styleguide che vieti tali dichiarazioni. Non è solo una questione su cui valga la pena litigare.


7
Noto che int i, j = 0;non ha operatori al suo interno. L'unica espressione in questa affermazione è 0e quindi la precedenza dell'operatore non vi si inserisce. Il parser non considera ,l'operatore virgola o =l'operatore di assegnazione; piuttosto, queste sono parti grammaticali della dichiarazione di dichiarazione.
Eric Lippert,

@EricLippert Per quanto riguarda le regole di precedenza, questa differenza è irrilevante: qualsiasi linguaggio in stile C che conosco utilizza le stesse precedenti in una dichiarazione come in altre espressioni. Qualsiasi altra cosa inviterebbe il disastro.
cmaster - ripristina monica il

but programmers can be expected to know the precedence of the most used operators by heart, tu dici. Nell'esempio che dai, non sono sicuro che la maggior parte dei programmatori (nella media) concepisca l'operatore di accesso dei membri o l'operatore di indice dell'array come un operatore in senso matematico, ma invece li considera più come nomi di linguaggio naturale e moltiplicazione operatore come il verbo. Ecco perché int i, j, k = 0;è un costrutto così diabolico, perché si presenta come l'analogo del linguaggio naturale di "int variabili i, j e k, sono dichiarati e devono essere impostati su 0"!
Steve

@Steve Come ricordi le regole di precedenza come programmatore, dipende da te. Se ti aiuta a pensare a loro come nomi della lingua, fallo. Tuttavia, in quel caso ti imbatterai in problemi quando vedi cose del genere *a[i], non penso che tu possa analizzarlo sufficientemente con l'analogia dei "nomi". Quanto a ciò int i, j, k = 0;, ciò potrebbe significare qualsiasi cosa se non osservi le regole: una terza interpretazione sarebbe dichiarare int i, quindi valutare je infine assegnare k = 0. Se non conosci la sintassi della tua lingua, non puoi analizzare tali costrutti. È il tuo problema se lo fai comunque.
cmaster - ripristina monica il

@cmaster, non stavo esprimendo la mia specifica strategia di memorizzazione haha. Non sono un programmatore C, quindi la mia familiarità con la precedenza dell'operatore in C è di seconda classe. Ma ciò che ho notato quando ho visto il tuo esempio è che non ho nemmeno pensato all'operatore di moltiplicazione come a una precedenza relativa all'operatore dell'indice di array. Cioè, non ho letto a[i]come operatore di indice applicato a, ma piuttosto ho letto entrambi insieme come un elemento sintattico irriducibile che specifica l'operando dell'operatore di moltiplicazione, e quindi non mi è stato nemmeno richiesto di valutare la precedenza. (1/2)
Steve
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.