首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ANSI-C语法-数组声明,如[*]等

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

Stack Overflow用户
提问于 2010-02-22 16:48:18
回答 3查看 2K关注 0票数 10

-联系-的ANSI C语法为数组声明提供了以下规则:

代码语言:javascript
复制
 (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 '[' ']'

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

  • 我可以使用(1) - (6),除了(3)只在C99?
  • (4)和(5)是做什么的?关键字“静态”让我感到困惑。
  • 在哪里使用(6)?
  • 以下两个函数原型之间有什么区别: void foo(int [*]);void foo(int []);

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-22 17:56:02

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

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

代码语言:javascript
复制
void foo(int a[static 3]) {
  ...
}

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

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

代码语言:javascript
复制
void foo(int n, int a[n]) /* `a` is VLA because `n` is not a constant */
{
  ...
}

当您声明原型时,您也可以这样做。

代码语言:javascript
复制
void foo(int n, int a[n]); /* `a` is VLA because `n` is not a constant */

但是,如果不指定参数名(在原型中是可以的),当然不能使用n作为数组大小。但是,如果您仍然必须告诉编译器数组将是一个VLA,则可以为此使用*

代码语言:javascript
复制
void foo(int, int a[*]); /* `a` is VLA because size is `*` */

注意,使用一维数组的示例不是一个好例子。即使您省略了*并将上面的函数声明为

代码语言:javascript
复制
void foo(int, int a[]);

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

代码语言:javascript
复制
void bar(int n, int m[n][n]) { /* 2D VLA */
  ...
}

原型可能如下所示

代码语言:javascript
复制
void bar(int n, int m[n][n]); /* 2D VLA */

或as

代码语言:javascript
复制
void bar(int, int m[*][*]); /* 2d VLA */

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

票数 15
EN

Stack Overflow用户

发布于 2010-02-22 17:52:42

我希望你不是在尝试从yacc规范中学习C语法!?您发布的链接似乎是基于国际标准化组织C99草案的。相关章节为6.7.5.2。其措辞很神秘(但可能不如yacc语法!)

票数 1
EN

Stack Overflow用户

发布于 2010-02-22 17:39:18

我的K&R2(涵盖并包括ANSI标准)似乎没有在文本或标准本身中提到任何关于[*]的内容。我也不能使标准中的官方语法接受这种语法。

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

我假设它显式地不指定数组的维度。但我只是猜。

Hmm...gcc接受

代码语言:javascript
复制
#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模式下继续接受。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2312490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档