【问题标题】:Why use "[*]" instead of "[]" in function prototype?为什么在函数原型中使用“[*]”而不是“[]”?
【发布时间】:2016-10-06 02:51:54
【问题描述】:

下面是 written 添加花哨的 * 星形语法以在函数原型中声明数组类型的基本原理 - 只是在我们进入问题之前进行澄清:

函数原型可以有可变长度的参数 使用特殊语法的数组类型(第 6.7.5.2 节),如 int minimum(int,int [*][*]); 这个名字和其他C原型一致 不需要指定参数。

但我非常有信心,我们可以通过仅使用像这样的未指定大小的普通数组来获得相同的效果(这里重写上面引用中给出的名为 minimum 的函数示例,我完全相信相同的功能(除了使用size_t 而不是int 作为第一个参数,这在这种情况下并不重要):

#include <stdio.h>


int minimum(size_t, int (*)[]);

int (main)()
{
    size_t sz;

    scanf("%zu", &sz);

    int vla[sz];

    for(size_t i = 0; i < sz; ++i)
        vla[i] = i;

    minimum(sizeof(vla) / sizeof(*vla), &vla);

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

    minimum(sizeof(a) / sizeof(*a), &a);
}


int minimum(size_t a, int (*b)[a])
{  
    for(size_t i = 0; i < sizeof(*b) / sizeof(**b); ++i)
        printf("%d ", (*b)[i]);

    return printf("\n");
}

因为我很确定标准中的某个地方指出 2 个数组只有在它们的大小相等时才兼容,而不管它们是否可变。

我的观点也得到证实,minimum 定义不会抱怨“冲突类型”,因为它的某些参数具有不兼容的类型(我认为两者都不是这样)这些数组的大小在编译时未指定 - 我指的是 minimum 的第二个参数。

除此之外,你能指出一个[*] 的单个用例,不能用普通的未指定大小的数组替换吗?

使用 clang 和 gcc 编译上述代码时没有任何警告。它还会产生预期的输出。

对于任何不了解 C 的人(或任何认为他/她知道 C 的人)- 类型数组的函数参数被隐式转换为“指向其元素类型的指针”。所以这个:

int minimum(int,int [*][*]);

调整为:

int minimum(int,int (*)[*]);

然后我认为它也可以写成:

int minimum(int,int (*)[]);

没有任何后果,并且具有与上述 2 种形式相同的行为。从而使[*] 表格过时。

【问题讨论】:

  • int (*)[] 不是 VLA。你得到哪个编译器错误?您是否尝试过至少编译?你想说啥?看起来像是讨论的开始。这不是讨论论坛。
  • @Olaf 我要求一个用例,其中函数原型的星形数组语法不能使用未指定大小的普通数组替换。是的,int (*)[] 不是 VLA,但你的意思是什么?
  • @Olaf 我知道我指的是在函数原型中声明具有未指定大小的 VLA 时的语法。在咆哮之前最好先阅读我的整个问题。
  • 请提供minimal reproducible example 您的意思。您的代码中没有使用 [*][*] 的工作示例。如果您的编译器出现问题,请再次非常仔细地阅读标准。 (它遵循相同的正确逻辑,例如将数组转换为函数参数的“指向第一个元素的指针”。
  • @Olaf 我相信所需要的一切都已经在问题中了。 [*][*](或者更确切地说是(*)[][][] 在这种情况下)的“工作”示例已经存在,我只是在问我为什么要使用 [*][*](*)[*] 代替。跨度>

标签: c arrays language-lawyer c99


【解决方案1】:

好的,除此之外 - 你能指出我 1 个 [*] 的单一用例吗? 用普通的未指定大小的数组替换?

当您传递三维 VLA 数组时,情况就是这样:

int minimum(size_t, int [*][*][*]);

这可以写成:

int minimum(size_t, int (*)[*][*]);

甚至使用未指定大小的数组:

int minimum(size_t, int (*)[][*]);

但是你不可能忽略或绕过最后一个索引,因此它必须在这样的声明中保持为[*]

【讨论】:

  • But you have no way to omit get around the of the last indice, so it has to stay as [*] in such declaration. 你能澄清你的意思吗?语法太差了,我听不懂你的意思。
  • @callyalater:已编辑,希望现在更好。
  • 好多了。谢谢你。现在这更有意义了。
  • @CisNOTthatGOODbutISOisTHATBAD,总而言之,您对自己问题的答案不感兴趣。
  • @CisNOTthatGOODbutISOisTHATBAD,感谢您的澄清。真的没有遇到。
【解决方案2】:

[] 只能用作多维数组最左边的“维度说明符”,而[*] 可以在任何地方使用。

在函数参数声明中,最左边(唯一!)[...] 无论如何都会调整为(*),因此可以在该位置使用(*),但会牺牲一些清晰度。

可以省略最左边的[...] 中的维度,留下空括号。这将使数组元素类型不完整。这没什么大不了的,因为可以在接近使用点的地方完成它(例如在函数定义中)。

下一个[...]需要一个数字或*,里面不能省略。这些声明

int foo (int [*][*][*]);
int foo (int (*)[*][*]);
int foo (int (*)[ ][*]);

都是兼容的,但没有一个不将第三维指定为* 或数字的兼容。如果第三维确实是可变的,* 是唯一的选择。

因此,[*] 至少对于维度 3 及以上是必需的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-07
    • 2021-11-06
    • 1970-01-01
    • 2011-11-22
    • 2014-01-12
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多