【问题标题】:Is this a valid way to declare an array in C?这是在 C 中声明数组的有效方法吗?
【发布时间】:2021-05-09 22:22:48
【问题描述】:

我知道您不应该将具有变量的数组声明为大小 ex。 int arr[n]; 因为如果不使用动态内存,数组的大小应该是静态的,但是如果你有这样的函数呢?这是否有效?它似乎运行得很好。它在函数内部声明的事实与它有什么关系吗?

int main() {
  int n;
  scanf("%d", &n);
  exampleFunc(n);

}

void exampleFunc(int const n) {
  int arr[n];
  for (int i = 0; i < num; i++) {
    arr[i] = i + 1;
  }
}

提前感谢您的帮助。我是 C 的菜鸟,我发现的所有资源都适用于其他语言。

【问题讨论】:

  • 您使用的是可变长度数组,它在C99中有效。
  • 这称为变长数组,是在 C99 中引入的。但在 C 标准的更高版本中,它被标记为可选。

标签: c declaration variable-length-array


【解决方案1】:

该语言的 1999 年修订版引入了可变长度数组,其中数组维度可以用运行时变量而不是编译时常量指定1。它们涵盖了 exampleFunc 中的确切用例,允许您声明一个直到运行时才知道其大小的本地数组而不必依赖 malloc

VLA 的使用受到限制 - 它们不能用作全局变量或声明为 static,不能在声明中使用初始值设定项,并且它们不能任意大。

在 C99 后的实施中,VLA 支持参差不齐,2011 年的修订版将其支持设为可选。为了完全安全,您应该检查语言版本和__STDC_NO_VLA__ 宏以确定您的实现是否支持它们2

void exampleFunc( const int n )
{
#if __STDC_VERSION__ >= 199901L && !defined(__STDC_NO_VLA__) 
  int arr[n];
#else
  int *arr = malloc( sizeof *arr * n );
#endif

// do stuff with arr

#if !(__STDC_VERSION__ >= 19901L && !defined(__STDC_NO_VLA__))
  free( arr );
#endif
}

  1. 尽管有名字,可变长度数组的大小对于任何给定的定义都是固定的;定义后无法调整大小。
  2. 就个人而言,我会颠倒该功能宏的含义,将其重命名为__STDC_VLA__,并且仅在支持 VLA 时定义它,但我不是标准委员会的成员。

【讨论】:

    【解决方案2】:

    来自GNU GCC documentation

    在 ISO C99 中允许使用可变长度自动数组。

    如果您使用的是std=c99 标志,则可以保证它是有效代码。但是,请记住,可变长度数组 (VLA) 不是 C++ 编程的标准部分。这是 C99 标准中引入的强制性功能。

    在实现尚未在 C11 支持中定义 __STDC_NO_VLA__ 标志之前,此功能确实成为可选功能。 Thanks to @trentcl 这个有效的细节。

    【讨论】:

    • 如果实现没有定义__STDC_NO_VLA__,它也是有效的C11。 VLA 是 C99 中的强制性功能,在 C11 中回滚为“可选”。
    • @trentcl 谢谢,我现在才知道。我已经更新了答案。
    【解决方案3】:

    对于初学者来说,for循环中有一个错字

    for (int i = 0; i < num; i++) {
    

    变量num 未声明。看来你的意思

    for (int i = 0; i < n; i++) {
    

    函数声明应放在其调用之前。

    用限定符 const 声明参数没有什么意义。

    void exampleFunc(int const n);
    

    这两个函数声明

    void exampleFunc(int const n);
    

    void exampleFunc(int n);
    

    声明同一个函数。

    函数内的数组声明

    int arr[n];
    
    如果您的编译器支持可变长度数组,

    将是有效的。否则编译器会报错,数组的大小应为整型常量表达式。

    可变长度数组应具有自动存储持续时间。因此,即使您的编译器支持可变长度数组,您也不能在任何函数之外声明它们,例如

    const int n = 10;
    int a[n];
    
    int main( void )
    {
        //...
    }
    

    你也不能在它们的声明中初始化可变长度数组。

    这是一个使用变长数组的演示程序。

    #include <stdio.h>
    
    void display_pattern( size_t n )
    {
        for ( size_t i = 0; i < n; i++ )
        {
            int a[i+1];
            
            for ( size_t j = 0; j < i + 1; j++ ) a[j] = ( i + j ) % n;
            
            for ( size_t j = 0; j < i + 1; j++ ) printf( "%d ", a[j] );
            putchar( '\n' );
        }
    }
    
    int main(void) 
    {
        display_pattern( 10 );
        
        return 0;
    }
    

    程序输出是

    0 
    1 2 
    2 3 4 
    3 4 5 6 
    4 5 6 7 8 
    5 6 7 8 9 0 
    6 7 8 9 0 1 2 
    7 8 9 0 1 2 3 4 
    8 9 0 1 2 3 4 5 6 
    9 0 1 2 3 4 5 6 7 8 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 1970-01-01
      • 2016-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多