为什么在编译时没有捕获数组文字大小不匹配?

时间:2012-12-18 11:35:37

标签: d

我有以下代码:

import std.stdio;

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

这个编译很好,然后在执行时中止,给出了这个错误:

arrays_init
object.Exception@src/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]

如果数组文字有3个项目,则运行正常,因此显然数组文字必须与静态数组的大小相匹配。但是这不应该给出编译错误,因为两者的大小都可以在编译时计算出来吗?

3 个答案:

答案 0 :(得分:9)

数组文字的类型为T[],即它们是动态数组,在编译时不知道它们的大小。

您的代码编译的原因与编译相同:

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

编译器根本不知道xs有多大。

在您的情况下,编译器可以在编译时知道,因为所有信息都在那里,但它将超出编译器有义务做的事情。严格解释代码,没有类型不匹配,因此编译。

数组文字作为动态数组的另一个副作用是你拥有的代码实际上会分配内存。它在堆上分配动态数组,复制到静态数组中,然后在回收内存之前必须等待垃圾收集周期。如果在紧密循环中初始化类似的数组,这可能会导致性能下降。

同样,编译器可以避免分配,但DMD至少不在当前版本(2.060)中。

答案 1 :(得分:7)

那是因为[1, 2](动态数组)的类型不保留数组中元素的数量,所以当编译器到达赋值(=)时,它不会不知道右侧表达式中有多少元素。

简单地说:编译器不够智能。

答案 2 :(得分:0)

可能是因为这句话:

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

在左侧,您在数组中说3个值,即您定义static array of 3 ints,但只分配两个值。

将其更改为:

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

问题应该得到解决。