为什么不指向VLA功能参数自动推断出它们的大小,目前它们有没有好用?

时间:2015-04-07 21:34:35

标签: c language-lawyer c11

根据我的理解,每个VLA都有一个隐藏的变量,它的大小可以被获得'由sizeof运营商提供。我不能到达的是指向功能参数中使用的VLA的指针 - 为什么它们的大小不会被自动推导并存储在这个隐藏变量中 - 为什么我们应该明确地提供它。在这种情况下,为什么我们应该使用它,因为我们已经有了指向未知大小数组的类型'?

我的意思是:

void func(size_t, int (*)[*]); //function accepting pointer to VLA

void func_1(size_t, int (*)[]); //function accepting pointer to array of unknown bound

void func(size_t sz, int (*parr)[sz]) //implementation of 'func'
{
    printf("%lu", sizeof(*parr) / sizeof(int));

    printf("%lu", sz);
}

void func_1(size_t sz, int(*parr)[]) //implementation of 'func_1'
{
    //printf("%lu", sizeof(*parr) / sizeof(int)); //error: invalid application of 'sizeof' to an incomplete type 'int []'

    printf("%lu", sz);
}

我可以看到使用' func'而不是' func_1'就是' sizeof'运营商将返回' sz'。

的初始值的副本

上述功能的示例用法:

int main()
{
    size_t sz = 3;

    int arr[sz];

    func(sizeof(arr) / sizeof(int), &arr);

    func_1(sizeof(arr) / sizeof(int), &arr);

    return 0;
}

为什么无法隐式指定指向VLA参数的指针大小?这至少可以很好地利用语法:

void func(int (*parr)[*]) // size copied from function argument
{
    printf("%lu", sizeof(*parr) / sizeof(int));

    printf("%lu", sz);
}

然后调用这个函数:

int main()
{
    size_t sz = 3;

    int arr[sz];

    func(&arr);

    return 0;
}

将导致数组隐藏的大小变量值为' 3'作为隐藏的参数传递给' func'创建类似于实例化以前的功能的代码' func'使用当前语法并使用' sizeof'运算符传递数组。

如果您有足够的好奇心将所提出的语法编译成任何Clang编译器 - 您将获得一个复活节彩蛋(;。

3 个答案:

答案 0 :(得分:1)

可变长度数组的长度仅在本地已知(因为它必须是堆栈分配存储并提供sizeof语义)。当它传递给函数时,它只是一个常规数组类型,因此必须明确传递大小。

答案 1 :(得分:1)

可变长度数组(VLA)的大小与类型相关联,而不是与对象相关联。

例如,给定:

size_t n = 41;
int vla[n+1];
printf("sizeof vla = %zu\n", sizeof vla);

编译器创建一个初始化为n+1的匿名对象,我将其称为_anon,并定义类型int[_anon],它是数组对象{{1}的类型}。 (请注意,稍后更改vla的值不会更改n的值或VLA类型的大小。)

你也可以写:

_anon

size_t n = 41; typedef int vla_t[n+1]; vla_t vla; 应用于表达式(在本例中,恰好是对象名称)会产生该表达式类型的大小。

sizeof内,func的类型不可见,因此无法获得其大小。 vla是指向未指定大小的parr 数组的指针。类型int(未指定大小的数组)和int[](长度为int[n+1]的可变长度数组)`兼容,但类型不同

答案 2 :(得分:0)

在几十年前应该废除的令人讨厌的可怕的kludge,但现在已经被太多的代码所依赖,C编译器认为数组类型的所有函数参数都等同于指针的参数 - 元素类型,是否指定了数组大小。

定义一个函数可能没有任何重大的技术困难,通过该语法可以传递任意大小的数组并自动知道它们有多大。不幸的是:

  1. 目前将数组传递给函数意味着将指针传递给第一个元素;添加一个新语法,这意味着其他东西会产生比它解决更多的混乱。

  2. 如果现有代码接收指针和整数,并将该指针视为标识指定长度数组的第一个元素,则传递"数组"一种期望一种新型"数组可能很棘手。

  3. 可以通过添加语法将指针/长度组合转换为"已知大小的数组来解决第二个问题。可以传递给接受这些东西的方法。然而,前一个问题可能是无法解决的,除非或直到C被一种不专注于指针的语言所取代,并且#34;优化"它们甚至不再相关。