int a [] = {1,2,}; Virgola strana consentita. Qualche motivo particolare?


335

Forse non vengo da questo pianeta, ma mi sembra che quanto segue dovrebbe essere un errore di sintassi:

int a[] = {1,2,}; //extra comma in the end

Ma non lo è. Sono stato sorpreso quando questo codice è stato compilato su Visual Studio, ma ho imparato a non fidarmi del compilatore MSVC per quanto riguarda le regole C ++, quindi ho controllato lo standard ed è consentito anche dallo standard. Puoi vedere 8.5.1 per le regole grammaticali se non mi credi.

inserisci qui la descrizione dell'immagine

Perché è permesso? Questa potrebbe essere una stupida domanda inutile, ma voglio che tu capisca perché lo sto chiedendo. Se fosse un sotto-caso di una regola grammaticale generale, capirei: hanno deciso di non rendere la grammatica generale più difficile solo per non consentire una virgola ridondante alla fine di un elenco di inizializzatori. Ma no, la virgola aggiuntiva è esplicitamente consentita. Ad esempio, non è consentito avere una virgola ridondante alla fine di un elenco di argomenti di chiamata di funzione (quando la funzione accetta ...), che è normale .

Quindi, di nuovo, c'è qualche motivo particolare per cui questa virgola ridondante è esplicitamente consentita?


10
Sembra che tutti concordino sulla "facilità di aggiungere una nuova linea", ma le persone che definiscono le specifiche linguistiche si preoccupano davvero di queste cose? Se sono davvero così comprensivi, allora perché non ignorano una mancanza ;quando è chiaro il prossimo token è in realtà un'affermazione successiva.
YetAnotherUser

35
@YetAnotherUser: Sì, i progettisti del linguaggio considerano queste cose. Consentire di eliminare i punti e virgola avrebbe un impatto molto maggiore e sarebbe altamente ambiguo in molte parti del linguaggio (ricordate, lo spazio bianco non è semantico in C). Una virgola extra in questo caso non è ambigua. Un punto e virgola aggiuntivo non è quasi mai ambiguo, e quindi è consentito anche. Nel caso in cui sia ambiguo (dopo un for()esempio), l'aggiunta di esso genera un avviso del compilatore.
Rob Napier,

5
@Tomalak: è ambiguo per un lettore umano ed è spesso un errore. Questo è il motivo per cui lancia un avvertimento. Allo stesso modo if (x = 1)non è ambiguo nella grammatica, ma è molto ambiguo per gli umani e quindi genera un avvertimento.
Rob Napier,

12
@Rob: neanche il tuo ifesempio è ambiguo. Non credo che "ambiguo" significhi ciò che pensi significhi!
Razze di leggerezza in orbita

5
Finché siamo d'accordo che è qualcosa di utile per il compilatore per proteggerci, mentre una virgola finale in una dichiarazione di array non è qualcosa di utile per il compilatore per proteggerci.
Rob Napier,

Risposte:


436

Semplifica la generazione di codice sorgente e anche la scrittura di codice che può essere facilmente esteso in un secondo momento. Considera cosa è necessario per aggiungere una voce aggiuntiva a:

int a[] = {
   1,
   2,
   3
};

... devi aggiungere la virgola alla riga esistente e aggiungere una nuova riga. Confrontalo con il caso in cui i tre già una virgola dopo di essa, in cui devi solo aggiungere una riga. Allo stesso modo, se vuoi rimuovere una linea, puoi farlo senza preoccuparti se è l'ultima linea o meno, e puoi riordinare le linee senza armeggiare con le virgole. Fondamentalmente significa che c'è un'uniformità nel modo in cui tratti le linee.

Ora pensa a generare codice. Qualcosa di simile (pseudo-codice):

output("int a[] = {");
for (int i = 0; i < items.length; i++) {
    output("%s, ", items[i]);
}
output("};");

Non devi preoccuparti se l'elemento corrente che stai scrivendo è il primo o l'ultimo. Molto più semplice


89
Inoltre, quando si utilizza un VCS, il "diff" tra due versioni è più pulito poiché solo una riga cambia quando viene aggiunto o rimosso un elemento.
Kevin Panko,

47
@ Néstor: Perché "sfortunato"? Qual è il rovescio della medaglia qui? Solo perché è stata presa in considerazione la generazione del codice (e la facile manipolazione) per una piccola parte della lingua non significa che debba essere la motivazione principale dietro tutte le decisioni nella lingua. Inferenza di tipo, rimozione di punti e virgola ecc. Hanno enormi implicazioni per la lingua. Stai allestendo una falsa dicotomia qui, IMO.
Jon Skeet,

18
@Néstor: Ecco dove il pragmatismo vince sul dogmatismo: perché deve essere completamente una cosa o l'altra completamente , quando è più utile essere una miscela di entrambi? Come si mette effettivamente in mezzo, potendo aggiungere una virgola alla fine? È questa un'incoerenza che ti ha mai impedito in qualche senso? In caso contrario, si prega di soppesare tale irrilevante ineleganza rispetto ai vantaggi pratici di consentire una virgola alla fine.
Jon Skeet,

8
@Mrchief: non è una questione di velocità di battitura - è una questione di semplicità, quando si copiano, rimuovono o riordinano gli oggetti. Mi ha semplificato la vita solo ieri. Senza svantaggi, perché non rendere la vita più facile? Per quanto riguarda il tentativo di puntare il dito su MS, sospetto fortemente che questo sia stato in C da prima ancora che esistesse Microsoft ... Dici che questa giustificazione sembra strana, ma scommetto che avvantaggia migliaia di sviluppatori in centinaia di aziende ogni giorno. Non è una spiegazione migliore che cercare qualcosa che avvantaggi gli autori di compilatori?
Jon Skeet,

6
Questo era in K&R C.
Ferruccio il

126

È utile se fai qualcosa del genere:

int a[] = {
  1,
  2,
  3, //You can delete this line and it's still valid
};

6
JavaScript supporta questa sintassi: var a = [1, 2,];così anche la maggior parte delle altre lingue che conosco ... ActionScript, Python, PHP.
Sean Fujiwara,

14
@Sean Questo causerà un errore di analisi in IE JavaScript, quindi fai attenzione!
Skilldrick,

10
Non per me in IE9. Ma fa qualcosa di strano ... crea un elemento nullo. Starò attento.
Sean Fujiwara,

5
@Sean Siamo spiacenti, siete sulla strada giusta - non è un errore di analisi in IE, ma sarà inserire un elemento in più per set undefined.
Skilldrick,

3
Più frustrante, JSON non supporta questa sintassi.
Timmmm,

38

Facile da usare per lo sviluppatore, penso.

int a[] = {
            1,
            2,
            2,
            2,
            2,
            2, /*line I could comment out easily without having to remove the previous comma*/
          }

Inoltre, se per qualsiasi motivo disponessi di uno strumento che ha generato codice per te; lo strumento non deve preoccuparsi se è l'ultimo elemento nell'inizializzazione o meno.


32

Ho sempre pensato che rendere più semplice aggiungere ulteriori elementi:

int a[] = {
            5,
            6,
          };

diventa semplicemente:

int a[] = { 
            5,
            6,
            7,
          };

in un secondo momento.


3
Non penso che rendere il montaggio leggermente più veloce sia una buona ragione per rovinare la sintassi. IMHO questa è solo un'altra strana caratteristica C ++.
Giorgio,

3
@Giorgio: Beh, è ​​ereditato da C. È del tutto possibile che sia solo una svista nelle specifiche del linguaggio originale, che sembra avere un effetto collaterale utile.
Oliver Charlesworth,

Ok, non sapevo che provenisse da C. Ho appena verificato che sia consentito anche in Java. Però sembra strano: secondo la mia intuizione la virgola è un separatore, non un terminatore. Inoltre, è possibile omettere l'ultima virgola. Quindi, è un terminatore, un separatore o entrambi? Ma OK, questa funzione è disponibile ed è bene saperlo.
Giorgio,

11
@Giorgio - il codice sorgente è per l'uomo, non per le macchine. Piccole cose come questa per impedirci di fare semplici errori di trasposizione sono una benedizione, non una svista. Per riferimento, funziona anche in PHP ed ECMAScript (e quindi JavaScript e ActionScript), sebbene non sia valido nella notazione di oggetti JavaScript (JSON) (ad es. [1,2,3,]OK ma {a:1, b:2, c:3,}non lo è).
Rilasciato il

1
@Grigio: più ci penso e più sono convinto che la sintassi di un linguaggio di programmazione dovrebbe essere il più semplice e coerente possibile e con il minor numero di eccezioni possibile: questo rende più facile l'apprendimento del linguaggio (meno regole da ricordare ). Il vantaggio di salvare una o due sequenze di tasti quando si aggiunge / rimuove un elemento in / da un elenco (che, a proposito, non lo faccio spesso rispetto al tempo totale che dedico alla programmazione) mi sembra piuttosto banale rispetto a avere una sintassi chiaramente definita.
Giorgio,

21

Tutto ciò che tutti dicono sulla facilità di aggiungere / rimuovere / generare linee è corretto, ma il vero posto che questa sintassi brilla è quando si uniscono i file di origine. Immagina di avere questo array:

int ints[] = {
    3,
    9
};

E supponi di aver controllato questo codice in un repository.

Quindi il tuo amico lo modifica, aggiungendo alla fine:

int ints[] = {
    3,
    9,
    12
};

E lo modifichi simultaneamente, aggiungendo all'inizio:

int ints[] = {
    1,
    3,
    9
};

Semanticamente questo tipo di operazioni (aggiungendo all'inizio, aggiungendo alla fine) dovrebbe essere completamente sicuro e il tuo software di controllo delle versioni (speriamo che git) dovrebbe essere in grado di automergere. Purtroppo, questo non è il caso perché la tua versione non ha una virgola dopo il 9 e quella del tuo amico. Considerando che, se la versione originale avesse il 9 finale, avrebbero automerged.

Quindi, la mia regola empirica è: usare la virgola finale se l'elenco si estende su più righe, non usarlo se l'elenco è su una sola riga.


15

La virgola finale credo sia consentita per motivi di compatibilità con le versioni precedenti. C'è molto codice esistente, principalmente generato automaticamente, che mette una virgola finale. Semplifica la scrittura di un loop senza condizioni speciali alla fine. per esempio

for_each(my_inits.begin(), my_inits.end(),
[](const std::string& value) { std::cout << value << ",\n"; });

Non c'è davvero alcun vantaggio per il programmatore.

PS Sebbene sia più facile generare automaticamente il codice in questo modo, in realtà mi sono sempre preoccupato di non mettere la virgola finale, gli sforzi sono minimi, la leggibilità è migliorata e questo è più importante. Scrivi il codice una volta, lo leggi molte volte.


5
Non sono completamente d'accordo; [Penso che] abbia trovato la sua strada in molte lingue create molto tempo dopo C proprio perché è vantaggioso per il programmatore essere in grado di spostarsi tra i contenuti dell'array, commentare le righe volenti o nolenti e così via, senza doversi preoccupare degli sciocchi errori di sintassi indotti dalla trasposizione. Non siamo già abbastanza stressati?
Rilasciato il

12
@Dereleased - con la stessa logica, perché non dovrebbe essere consentito il trascinamento (nulla), che ne dici int a = b + c +;o if(a && b &&);sarà più semplice copiare e incollare qualsiasi cosa alla fine e più facile scrivere generatori di codice. Questo problema è sia banale che soggettivo, in questi casi è sempre bene fare ciò che è meglio per il lettore di codici.
Gene Bushuyev,

1
@Gene Bushuyev: Esatto! Spesso ho lunghe espressioni con + o &&, con l'operatore alla fine della linea e, ovviamente, devo passare un po 'di tempo extra quando voglio rimuovere l'ultimo operando dell'espressione. Penso che questa sintassi virgola sia davvero strana!
Giorgio,

2
@GeneBushuyev - Non sono d'accordo su quelli. Mentre consentire le virgole finali nelle matrici e simili è una funzione di rimozione dei bug e semplifica la vita come programmatore, per pura leggibilità prenderei le misure per rimuovere le frasi finali E (&&), i temi e altri operatori vari dal condizionale dichiarazioni. È semplicemente brutto, IMO.
Sune Rasmussen,

2
Per quanto riguarda l' &&operatore, a volte faccio condizionali in if (true \n && b1 \n && b2)modo da poter aggiungere e rimuovere le linee di cui ho bisogno.
Christian Mann,

12

Uno dei motivi per cui è consentito, per quanto ne so, è che dovrebbe essere semplice generare automaticamente il codice; non è necessaria alcuna gestione speciale per l'ultimo elemento.


11

Rende più facili i generatori di codice che emettono array o enumerazioni.

Immaginare:

std::cout << "enum Items {\n";
for(Items::iterator i(items.begin()), j(items.end); i != j; ++i)
    std::cout << *i << ",\n";
std::cout << "};\n";

Vale a dire, non è necessario eseguire una gestione speciale del primo o dell'ultimo elemento per evitare di sputare la virgola finale.

Se il generatore di codice è scritto in Python, ad esempio, è facile evitare di sputare la virgola finale usando la str.join()funzione:

print("enum Items {")
print(",\n".join(items))
print("}")

10

Sono sorpreso dopo tutto questo tempo che nessuno ha citato il Manuale di riferimento C ++ annotato ( ARM ), dice quanto segue su [dcl.init] con enfasi il mio:

Esistono chiaramente troppe notazioni per le inizializzazioni, ma ognuna sembra servire bene un particolare stile di utilizzo. La notazione = {initializer_list, opt} è stata ereditata da C e serve bene per l'inizializzazione di strutture e matrici di dati. [...]

sebbene la grammatica si sia evoluta da quando è stato scritto ARM, l'origine rimane.

e possiamo andare alla logica C99 per vedere perché questo è stato permesso in C e dice:

K&R consente una virgola finale in un inizializzatore alla fine di un elenco di inizializzatori. Lo standard ha mantenuto questa sintassi, poiché fornisce flessibilità nell'aggiunta o eliminazione di membri da un elenco di inizializzatori e semplifica la generazione automatica di tali elenchi.


1
Considerare la risposta più sostenuta dalla letteratura e la vera fonte di questa funzionalità.
Marko,

10

Vedo un caso d'uso che non è stato menzionato in altre risposte, i nostri macro preferiti:

int a [] = {
#ifdef A
    1, //this can be last if B and C is undefined
#endif
#ifdef B
    2,
#endif
#ifdef C
    3,
#endif
};

L'aggiunta di macro per gestire l'ultimo ,sarebbe un grande dolore. Con questo piccolo cambiamento nella sintassi, questo è banale da gestire. E questo è più importante del codice generato dalla macchina perché di solito è molto più facile farlo in Turing langue completo rispetto a un preprocesor molto limitato.


7

L'unico linguaggio in cui - in pratica * - non è consentito è Javascript e causa una quantità innumerevole di problemi. Ad esempio, se copi e incolli una linea dal centro dell'array, la incolli alla fine e dimentichi di rimuovere la virgola, il tuo sito verrà completamente interrotto per i tuoi visitatori IE.

* In teoria è consentito, ma Internet Explorer non segue lo standard e lo considera un errore


Gli "array" di JavaScript (che sono solo oggetti con una proprietà di lunghezza magica) sono comunque piuttosto insoliti: var x = [,,,]è legale (tranne in IE <9, ma la specifica dice che è legale)
Peter C

Secondo le specifiche ECMAScript, è perfettamente valido; in teoria dovrebbe funzionare in qualsiasi browser che implementa JavaScript in base a detta specifica, in particolare la parte della specifica qui trovata .
Rilasciato il

1
Sfortunatamente JavaScript si basa sulla creazione di app per il pubblico. Quindi no, non è perfettamente valido quando circa il 50% degli utenti avrebbe problemi ad usare la tua app. E sì, se potessi vieterei IE <9 - troppe ore impiegate a fare solo un buon codice lavorando lì ...
kgadek,

@Dere: sì, ho detto altrettanto nella mia risposta =)
Thomas Bonini,

@Dereleased microsoft inventa le proprie specifiche e comanda che altri rispettino almeno quella mentalità che sta cambiando (grazie a dio)
Chris McGrath

7

È più facile per le macchine, ovvero l'analisi e la generazione di codice. È anche più facile per gli esseri umani, ovvero modifica, commento e eleganza visiva tramite coerenza.

Supponendo C, scriveresti quanto segue?

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    puts("Line 1");
    puts("Line 2");
    puts("Line 3");

    return EXIT_SUCCESS
}

No. Non solo perché la dichiarazione finale è un errore, ma anche perché è incoerente. Quindi perché fare lo stesso con le collezioni? Anche nelle lingue che ti consentono di omettere gli ultimi punti e virgole e virgole, alla community di solito non piace. La comunità Perl, ad esempio, non sembra voler omettere i punti e virgola, escludendo le righe. Lo applicano anche alle virgole.

Non omettere le virgole nelle raccolte multilinea per lo stesso motivo per cui non si omettono punti e virgola per blocchi di codice multilinea. Voglio dire, non lo faresti anche se la lingua lo permettesse, giusto? Destra?


Ci sono lingue (es. Pascal) che lo consentono. Cioè devi scegliere tra; come terminatore (C) o come separatore (Pascal). Lo stesso per ",". Sarebbe ok per me se ',' è un terminatore, ma quindi {1, 2, 3} deve essere un errore di sintassi.
Giorgio,

6

Il motivo è banale: facilità di aggiunta / rimozione di linee.

Immagina il seguente codice:

int a[] = {
   1,
   2,
   //3, // - not needed any more
};

Ora, puoi facilmente aggiungere / rimuovere elementi dall'elenco senza dover aggiungere / rimuovere la virgola finale a volte.

Contrariamente ad altre risposte, non credo davvero che la facilità di generare l'elenco sia un motivo valido: dopo tutto, è banale che il codice specifichi l'ultima riga (o la prima). I generatori di codice vengono scritti una volta e utilizzati più volte.


6

Consente a ogni riga di seguire la stessa forma. In primo luogo ciò semplifica l'aggiunta di nuove righe e un sistema di controllo della versione tiene traccia delle modifiche in modo significativo e consente anche di analizzare il codice più facilmente. Non riesco a pensare a un motivo tecnico.


5

Ciò è consentito per proteggere da errori causati dallo spostamento di elementi in un lungo elenco.

Ad esempio, supponiamo di avere un codice simile a questo.

#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
    std::string messages[] = {
        "Stack Overflow",
        "Super User",
        "Server Fault"
    };
    size_t i;
    for (i = 0; i < ARRAY_SIZE(messages); i++) {
        std::cout << messages[i] << std::endl;
    }
}

Ed è fantastico, in quanto mostra la trilogia originale dei siti di Stack Exchange.

Stack Overflow
Super User
Server Fault

Ma c'è un problema con esso. Vedete, il piè di pagina su questo sito Web mostra Server Fault prima di Super User. Meglio risolverlo prima che qualcuno se ne accorga.

#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
    std::string messages[] = {
        "Stack Overflow",
        "Server Fault"
        "Super User",
    };
    size_t i;
    for (i = 0; i < ARRAY_SIZE(messages); i++) {
        std::cout << messages[i] << std::endl;
    }
}

Dopotutto, spostare le linee non potrebbe essere così difficile, vero?

Stack Overflow
Server FaultSuper User

Lo so, non esiste un sito Web chiamato "Server FaultSuper User", ma il nostro compilatore afferma che esiste. Ora, il problema è che C ha una funzione di concatenazione di stringhe, che consente di scrivere due stringhe tra virgolette doppie e concatenarle usando nulla (problema simile può verificarsi anche con numeri interi, poiché il -segno ha significati multipli).

E se la matrice originale avesse una virgola inutile alla fine? Bene, le linee sarebbero state spostate, ma un tale bug non si sarebbe verificato. È facile perdere qualcosa di piccolo come una virgola. Se ricordi di inserire una virgola dopo ogni elemento dell'array, tale errore non può accadere. Non vorrai perdere quattro ore a eseguire il debug di qualcosa, finché non scoprirai che la virgola è la causa dei tuoi problemi .


4

Come molte altre cose, la virgola finale in un inizializzatore di array è una delle cose che C ++ ha ereditato da C (e dovrà supportare per sempre). Una visione totalmente diversa da quelle qui collocate è menzionata nel libro "Deep C secrets" .

Qui dopo un esempio con più di un "paradosso virgola":

char *available_resources[] = {
"color monitor"           ,
"big disk"                ,
"Cray"                      /* whoa! no comma! */
"on-line drawing routines",
"mouse"                   ,
"keyboard"                ,
"power cables"            , /* and what's this extra comma? */
};

noi leggiamo :

... quella virgola finale dopo l'inizializzatore finale non è un errore di battitura, ma un blip nella sintassi riportata dalla C aborigena . La sua presenza o assenza è consentita ma non ha significato . La giustificazione richiesta nella logica ANSI è che facilita la generazione automatizzata di C. L'affermazione sarebbe più credibile se le virgole finali fossero consentite in ogni elenco con virgola sepa , come nelle dichiarazioni enum o in più dichiaratori variabili in un'unica dichiarazione. Non sono.

... per me questo ha più senso


2
Il divieto contro la virgola nel enumcaso è alquanto interessante, poiché è il caso in cui la virgola mancante porrebbe la minima ambiguità. Dato struct foo arr[] = {{1,2,3,4,5}, {3,4,5,6,7}, }; ci sono due significati sensibili che il linguaggio potrebbe assegnare: creare un array a due elementi o creare un array a tre elementi in cui l'ultimo elemento ha valori predefiniti. Se C avesse adottato l'interpretazione successiva, enum foo {moe, larry, curly, };
vedrei

1
... dato che C è disposto a ignorare la virgola in un caso in cui avrebbe potuto ragionevolmente (ma non era) assegnato un significato significativo (che sarebbe un argomento forte a favore di vietarlo lì) è curioso che non lo sia è disposto nel caso in cui la virgola non possa avere un significato [anche se si interpretasse enum foo {moe,,larry,curly,};come saltare un numero tra moee larry, in genere non importa se la virgola finale è stata elaborata o ignorata. L'unico caso in cui potrebbe importare sarebbe se l'ultimo articolo fosse il valore massimo per il tipo dichiarato e che ...
supercat

1
... potrebbe essere gestito semplicemente dicendo che l'overflow che si verifica dopo l'ultimo valore di enumerazione assegnato dovrebbe essere ignorato.
supercat

@supercat Ci sono lingue, come C #, in cui la ricerca progettuale a priori arriva fino a considerare le funzionalità IDE e l'integrazione quando si sviluppa il linguaggio. C non era (e non poteva essere) una di queste lingue.
Nikos Athanasiou,

Anche con linguaggi come C #, la modifica degli obiettivi di progettazione ha comportato alcune incoerenze di progettazione piuttosto gravi. Ad esempio, il linguaggio si è astenuto dal supportare qualsiasi forma di sovraccarico del tipo di ritorno per metodi e operatori normali (anche se il framework sottostante potrebbe supportarlo) perché era visto come contrario all'obiettivo di avere un linguaggio semplice da compilare, ma La valutazione lambda include regole di inferenza del tipo la cui risoluzione è NP-completa. L'aggiunta di nuove regole di sovraccarico del metodo / operatore potrebbe violare il codice esistente (anche se penso che buone regole possano minimizzare tale pericolo) ...
supercat

2

Oltre alla facilità di generazione e modifica del codice, se si desidera implementare un parser, questo tipo di grammatica è più semplice e più facile da implementare. C # segue questa regola in diversi punti in cui esiste un elenco di elementi separati da virgola, come gli elementi in una enumdefinizione.


1

Rende più semplice la generazione di codice in quanto è necessario solo aggiungere una riga e non è necessario trattare l'aggiunta dell'ultima voce come se fosse un caso speciale. Ciò è particolarmente vero quando si utilizzano le macro per generare codice. C'è una spinta a cercare di eliminare la necessità di macro dalla lingua, ma gran parte della lingua si è evoluta di pari passo con la disponibilità delle macro. La virgola aggiuntiva consente di definire e utilizzare macro come le seguenti:

#define LIST_BEGIN int a[] = {
#define LIST_ENTRY(x) x,
#define LIST_END };

Uso:

LIST_BEGIN
   LIST_ENTRY(1)
   LIST_ENTRY(2)
LIST_END

Questo è un esempio molto semplificato, ma spesso questo modello viene utilizzato dalle macro per definire elementi come mappe e tabelle di invio, messaggio, evento o traduzione. Se alla fine non fosse consentita una virgola, avremmo bisogno di uno speciale:

#define LIST_LAST_ENTRY(x) x

e sarebbe molto imbarazzante da usare.


0

In modo che quando due persone aggiungono un nuovo elemento in un elenco su rami separati, Git può unire correttamente le modifiche, perché Git funziona su una linea.


-4

Se si utilizza un array senza lunghezza specificata, VC ++ 6.0 può identificarne automaticamente la lunghezza, quindi se si utilizza "int a [] = {1,2,};" la lunghezza di a è 3, ma l'ultima non ha ' t inizializzato, puoi usare "cout <


È un bug per VC6 che non è conforme allo standard?
Thomson,
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.