2012-12-18 11 views
7

Ho il seguente codice:Perché la mancata corrispondenza delle dimensioni letterali dell'array non viene catturata al momento della compilazione?

import std.stdio; 

int main(string[] args) 
{ 
    int[3] my_array = [1, 2]; 
    return 0; 
} 

Questo compila bene, e poi interrompe quando eseguito, dando questo errore:

arrays_init 
[email protected]/rt/arraycat.d(31): lengths don't match for array copy 
---------------- 
arrays_init(_Dmain+0x64) [0x416bbc] 
arrays_init(extern (C) int rt.dmain2.main(int, char**).void runMain()+0x1c) [0x418c5c] 
arrays_init(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x4185d6] 
arrays_init(extern (C) int rt.dmain2.main(int, char**).void runAll()+0x3b) [0x418ca3] 
arrays_init(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x4185d6] 
arrays_init(main+0xd1) [0x418561] 
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f60bc41d30d] 

Questo funziona bene se l'array letterale dispone di 3 elementi, così apparentemente la array letteral deve corrispondere alla dimensione dell'array statico. Ma questo non dovrebbe dare un errore di compilazione poiché la dimensione di entrambi può essere calcolata al momento della compilazione?

risposta

9

I valori letterali di array sono di tipo T[], ovvero sono matrici dinamiche che non sono consapevoli delle loro dimensioni in fase di compilazione.

Il codice compilato per lo stesso motivo questo compila:

void foo(int[] xs) 
{ 
    int[3] ys = xs; 
    ... 
} 

Il compilatore semplicemente non sa quanto grande è xs.

Nel tuo caso, il compilatore potrebbe conoscono al momento della compilazione, perché tutte le informazioni sono lì, ma sarebbe andato al di là di ciò che il compilatore è obbligato a farlo. Interpretando il codice rigorosamente, non vi è alcun tipo di disallineamento, quindi compila.

Un altro effetto collaterale dei matrici di array come array dinamici è che il codice che si possiede effettivamente alloca la memoria. Alloca la matrice dinamica sull'heap, copia nell'array statico e quindi è necessario attendere un ciclo di garbage collection prima che la memoria venga recuperata. Questo può essere una causa di cattive prestazioni se si inizializzano array come quello in un ciclo stretto.

Nuovamente, il compilatore potrebbe evitare l'assegnazione, ma DMD almeno non funziona nella versione corrente (2.060).

+0

+1: la risposta corretta! –

+0

Fortunatamente, è il piano di farlo in modo che il codice dell'OP non si allochi più (nel qual caso, probabilmente produrrà un errore), ma non è stato abbastanza alto sulla lista TODO da fare ancora . –

+0

Forse potrebbero usare la sintassi letterale dell'array C per inizializzare gli array statici. – Scooter

0

Probabilmente a causa di questa linea:

int[3] my_array = [1, 2]; 

sul lato sinistro si stanno dicendo 3 valori in serie vale a dire che si sta definendo static array of 3 ints, ma assegnando solo due valori.

modificarla in:

int[3] my_array = [1, 2, 3]; 

ed il problema dovrebbe ottenere risolto.

+2

Modo per leggere completamente la domanda? –

+0

@CyberShadow: Sì, l'ho perso la prima volta. – Azodious

+2

E la seconda volta. –

7

Questo sarebbe perché il tipo di [1, 2] (matrice dinamica) non conserva il numero di elementi nella matrice, quindi, al momento compilatore ottiene all'assegnazione (=), non sa quanti elementi sono nell'espressione sul lato destro.

Per dirla semplicemente: il compilatore semplicemente non è abbastanza intelligente.

+1

Che cosa dice la proprietà .length degli array dinamici - solo la capacità ?? – Scooter

+1

@Scooter: la proprietà length è _dynamic_ cioè un runtime thang. In teoria, il compilatore potrebbe dedurre tutte queste informazioni in fase di compilazione, allo stesso modo in cui lo possono fare gli occhi; ma il linguaggio non lo richiede e semplicemente non lo fa. –

Problemi correlati