ANSI-C 语法 - 数组声明,如 [*] 等

发布于 2024-08-22 16:16:29 字数 879 浏览 5 评论 0原文

-link- 中的 ANSI C 语法给了我以下规则对于数组声明:

 (1) | direct_declarator '[' type_qualifier_list assignment_expression ']'
 (2) | direct_declarator '[' type_qualifier_list ']'
 (3) | direct_declarator '[' assignment_expression ']'
 (4) | direct_declarator '[' STATIC type_qualifier_list assignment_expression ']'
 (5) | direct_declarator '[' type_qualifier_list STATIC assignment_expression ']'
 (6) | direct_declarator '[' type_qualifier_list '*' ']'
 (7) | direct_declarator '[' '*' ']'
 (8) | direct_declarator '[' ']'

现在我有一些关于这些的问题:

  • 我可以仅在 C99 中使用 (1) - (6) except (3) 吗?
  • (4)和(5)有什么用?关键字“静态”让我感到困惑。
  • 在哪里使用(6)?
  • 以下两个函数原型有什么区别:

    void foo(int [*]);

    void foo(int []);

谢谢。

The ANSI C grammar from -link- give me the following rules for array declarations:

 (1) | direct_declarator '[' type_qualifier_list assignment_expression ']'
 (2) | direct_declarator '[' type_qualifier_list ']'
 (3) | direct_declarator '[' assignment_expression ']'
 (4) | direct_declarator '[' STATIC type_qualifier_list assignment_expression ']'
 (5) | direct_declarator '[' type_qualifier_list STATIC assignment_expression ']'
 (6) | direct_declarator '[' type_qualifier_list '*' ']'
 (7) | direct_declarator '[' '*' ']'
 (8) | direct_declarator '[' ']'

Now I have a some questions about these:

  • Can I use (1) - (6) except (3) only in C99?
  • What are (4) and (5) for? The keyword 'static' confuses me.
  • Where to use (6)?
  • What's the difference between the following two function prototypes:

    void foo(int [*]); and

    void foo(int []);

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

罗罗贝儿 2024-08-29 16:16:29

在 C89/90 中,不能在数组声明的大小部分中使用类型限定符或static。这些功能是 C99 特有的。

数组声明中的static 告诉编译器您承诺指定数量的元素将始终出现在作为实际参数传递的数组中。这可能有助于编译器生成更高效的代码。如果您在实际代码中违反了承诺(即传递较小的数组),则行为是未定义的。例如,

void foo(int a[static 3]) {
  ...
}

int main() {
  int a[4], b[2];
  foo(a); /* OK */
  foo(b); /* Undefined behavior */
}

数组声明的 size 部分中的 * 仅在函数原型声明中使用。它表明该数组具有可变长度(VLA)。例如,在函数定义中,您可以使用具有具体运行时大小的 VLA

void foo(int n, int a[n]) /* `a` is VLA because `n` is not a constant */
{
  ...
}

当您声明原型时,您可以执行相同的操作

void foo(int n, int a[n]); /* `a` is VLA because `n` is not a constant */

,但如果您不指定参数名称(这在原型中是可以的),您可以当然,不要使用 n 作为数组大小。然而,如果您仍然需要告诉编译器该数组将是一个 VLA,您可以使用 * 来实现此目的。

void foo(int, int a[*]); /* `a` is VLA because size is `*` */

请注意,带有一维数组的示例不是一个好的示例。即使您省略 * 并声明上述函数,

void foo(int, int a[]);

代码仍然可以正常工作,因为在函数参数声明中,数组类型无论如何都会隐式替换为指针类型。但是一旦开始使用多维数组,正确使用 * 就变得很重要。例如,如果函数被定义为

void bar(int n, int m[n][n]) { /* 2D VLA */
  ...
}

原型可能如下所示

void bar(int n, int m[n][n]); /* 2D VLA */

void bar(int, int m[*][*]); /* 2d VLA */

在后一种情况下,可以省略第一个 * (因为数组到指针的替换),但不能省略第二个*

You can't use type qualifiers or static in size portion of array declaration in C89/90. These features are specific to C99.

static in array declaration tells the compiler that you promise that the specified number of elements will always be present in the array passed as the actual argument. This might help compilers to generate more efficient code. If you violate your promise in the actual code (i.e. pass a smaller array), the behavior is undefined. For example,

void foo(int a[static 3]) {
  ...
}

int main() {
  int a[4], b[2];
  foo(a); /* OK */
  foo(b); /* Undefined behavior */
}

The * in size portion of array declaration is used in function prototype declarations only. It indicates that the array has variable length (VLA). For example, in the function definition you can use a VLA with a concrete run-time size

void foo(int n, int a[n]) /* `a` is VLA because `n` is not a constant */
{
  ...
}

When you declare the prototype you can do the same

void foo(int n, int a[n]); /* `a` is VLA because `n` is not a constant */

but if you don't specify the parameter names (which is OK in the prototype), you can't use n as array size of course. Yet, if you still have to tell the compiler that the array is going to be a VLA, you can use the * for that purpose

void foo(int, int a[*]); /* `a` is VLA because size is `*` */

Note, that the example with a 1D array is not a good one. Even if you omit the * and declare the above function as

void foo(int, int a[]);

then the code will still work fine, because in function parameter declarations array type is implicitly replaced with pointer type anyway. But once you start using multi-dimensional arrays, the proper use of * becomes important. For example, if the function is defined as

void bar(int n, int m[n][n]) { /* 2D VLA */
  ...
}

the the prototype might look as follows

void bar(int n, int m[n][n]); /* 2D VLA */

or as

void bar(int, int m[*][*]); /* 2d VLA */

In the latter case the first * can be omitted (because of the array-to-pointer replacement), but not the second *.

洋洋洒洒 2024-08-29 16:16:29

我希望您不是试图从 yacc 规范中学习 C 语法!?您发布的链接似乎基于 ISO C99草稿。相关章节为 6.7.5.2。措辞很晦涩(但也许不如 yacc 语法那么晦涩!)

I hope you are not trying to learn C grammar from a yacc specification!? The link you posted appears to be based on the ISO C99 draft. The relevant section is 6.7.5.2. The wording is arcane (but less so than the yacc syntax perhaps!)

向地狱狂奔 2024-08-29 16:16:29

我的 K&R2nd(涵盖并包括 ANSI 标准)似乎没有在文本中或标准本身中提及任何有关 [*] 的内容。我也无法使标准中的官方语法接受该语法。

它可能与 K&R c 有关(虽然我似乎不记得了),可能是一个常见的扩展,或者是一个最终没有成为标准的提案。

假设它使数组的维度明确未指定。但我只是猜测。


嗯...gcc 接受

#include <stdio.h>

void f(int s, int a[*]);

int main(void){
  int a[2] = {0};
  f(2,a);
  return 0;
}

void f(int s, int a[]){
  int i;
  for (i=0; i<s; ++i){
    printf("%d\n",a[i]);
  }
}

ansi、c89 和 c99 模式;即使使用 -Wall 也不会发出警告。请注意,它不喜欢函数定义中的 [*] 语法。添加 -pedantic 使其抱怨 c89 和 ansi 模式中的 [*] 语法,但它继续在 c99 模式中接受。

My K&R2nd (which covers and includes the ANSI standard) does not seem to say anything about [*] either in the text, or in the standard itself. Nor can I make the official grammar in the standard accept that syntax.

It may be related to K&R c (though I don't seem to recall it), may have been a common extension, or have been a proposal that ultimately didn't make the standard.

I would assume it makes the dimension of the array explicitly unspecified. But I'm just guessing.


Hmm...gcc accepts

#include <stdio.h>

void f(int s, int a[*]);

int main(void){
  int a[2] = {0};
  f(2,a);
  return 0;
}

void f(int s, int a[]){
  int i;
  for (i=0; i<s; ++i){
    printf("%d\n",a[i]);
  }
}

in ansi, c89 and c99 mode; issuing no warnings even with -Wall. Note that it did not like the [*] syntax in the function definition. Adding -pedantic made it complain about the [*] syntax in c89 and ansi modes, but it continued to accept in in c99 mode.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文