2012-12-18 11 views
7

Mam następujący kod:Dlaczego nie występuje niezgodność rozmiaru literowego tablicy w czasie kompilacji?

import std.stdio; 

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

To kompiluje grzywny, a następnie przerywa po uruchomieniu, co daje ten błąd:

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] 

To działa dobrze jeśli tablica dosłowne ma 3 pozycje, więc widocznie tablica literowa musi pasować do rozmiaru tablicy statycznej. Ale czy nie powinno to spowodować błędu kompilacji, ponieważ rozmiar obu można obliczyć w czasie kompilacji?

Odpowiedz

9

Literały tablicy są typu T[], tj. Są tablicami dynamicznymi, które nie są świadome swojego rozmiaru podczas kompilacji.

Kod kompiluje z tego samego powodu to kompiluje:

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

Kompilator po prostu nie wie, jak duże xs jest.

W twoim przypadku kompilator może wiedzieć, w czasie kompilacji, ponieważ wszystkie informacje są tam, ale będzie to wykraczać poza to, co kompilator jest zobowiązany zrobić. Interpretując ściśle kod, nie występuje niezgodność typów, więc kompiluje się.

Innym skutkiem ubocznym literałów tablicowych będących tablicami dynamicznymi jest fakt, że posiadany kod faktycznie przydzieli pamięć. Przydziela tablicę dynamiczną na stercie, kopiuje do tablicy statycznej, a następnie trzeba czekać na cykl czyszczenia pamięci przed odzyskaniem pamięci. Może to być przyczyną złej wydajności przy inicjalizacji takich tablic w ciasnej pętli.

Ponownie, kompilator może uniknąć alokacji, ale DMD przynajmniej nie ma w obecnej wersji (2.060).

+0

+1: Prawidłowa odpowiedź! –

+0

Na szczęście, jest to plan polegający na tym, że kod PO nie będzie już przydzielany (w takim przypadku prawdopodobnie spowoduje to błąd), ale nie jest wystarczająco wysoki na liście TODO, która zostanie jeszcze wykonana . –

+0

Być może mogliby użyć literalnej składni C do inicjalizacji tablic statycznych. – Scooter

0

Prawdopodobnie z powodu tej linii:

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

na lewej stronie mówisz 3 wartości w tablicy tj definiowania static array of 3 ints, ale przypisywanie tylko dwie wartości.

go zmienić na:

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

i problemu powinno się rozwiązać.

+2

Sposób na całkowite błędne odczytanie pytania? –

+0

@CyberShadow: Tak, przegapiłem to po raz pierwszy. – Azodious

+2

I drugi raz. –

7

To dlatego, że typ [1, 2] (tablica dynamiczna) nie zachowuje liczby elementów w tablicy, więc do czasu, gdy kompilator dotrze do zadania (=), nie wie, ile elementów jest w wyrażeniu po prawej stronie.

Mówiąc prościej: kompilator po prostu nie jest wystarczająco inteligentny.

+1

Co mówi własność .length dynamicznych tablic - tylko pojemność? – Scooter

+1

@Scooter: Właściwością length jest _dynamic_, np. Thang środowiska wykonawczego. Kompilator może zostać utworzony w teorii, aby wyprowadzić wszystkie te informacje w czasie kompilacji, w ten sam sposób, w jaki potrafią twoje oczy; ale język nie wymaga tego, a po prostu nie. –

Powiązane problemy