使用const int

时间:2016-01-25 16:39:11

标签: c arrays size const

当我尝试运行它时,它给出了一个错误,指出变量a中的值不是常量。这对我没有意义,因为我明确地使变量a保持不变。数组的大小是否必须更加恒定?含义,仅#define a 5,或将其初始化为int arr[5]或使用malloc?我做了什么错了?

int main{

   const int a = 5;
   int i;
   int arr [a];

   for (i = 0; i < 5; i++) {
      arr[i] = i * 2;
   }

  printf("%d", arr[1]);
  return 0;
}

3 个答案:

答案 0 :(得分:9)

在C中,const应该被理解为只读。它没有定义编译时间。

const int a = 5;

此处a C standard所需的常量表达式:

  

6.7.9初始化
  4具有静态或线程存储持续时间的对象的初始值设定项中的所有表达式都应是常量   表达式或字符串文字。

因此错误表明您正在使用C89 / C90编译器。您可以阅读用户对a的输入,并声明variable length array,这是一个C99功能,具有自动存储持续时间。

使用#define是另一种方式。但它只是一个文本替换,并定义了一个具有自动存储持续时间的阵列。它与自己定义int arr[5];相同。

如果要在动态存储上分配内存(通常称为&#34; heap&#34;),则必须使用malloc()族函数,这些函数在程序执行期间具有生命周期,直到您调用{ {1}}就可以了。

(请注意,free()的此行为仅在C中.C ++与此不同,并且可以按预期工作。)

如果我在C89中编译代码,它将失败:

const

因为C89不支持VLA(尽管gcc支持an extension,即使在C89 / C90中也是如此)。因此,如果您使用的是不支持C99的编译器,那么您就无法使用VLA。 例如,visual studio并不完全支持所有C99和C11功能。虽然,Visual studio 2015 support most C99 features,但VLA不是其中之一。

但是相同的代码在C99和C11中编译没有任何问题:

#include <stdio.h>

int main(){

   const int a = 5;
   int i;
   int arr [a];

   for (i = 0; i < 5; i++) {
      arr[i] = i * 2;
   }

  printf("%d", arr[1]);
  return 0;
}

$ gcc -Wall -Wextra -std=c89 -pedantic-errors test.c
test.c: In function âmainâ:
test.c:7:4: error: ISO C90 forbids variable length array âarrâ [-Wvla]
    int arr [a];
    ^

这是因为在C99中添加了可变长度阵列(VLA)。请注意,VLA已在C11标准中成为可选项。因此,实现可能不支持C11中的VLA。 您需要针对$ gcc -Wall -Wextra -std=c99 -pedantic-errors t.c $ gcc -Wall -Wextra -std=c11 -pedantic-errors t.c 进行测试,以检查您的实施是否不支持VLA。

来自6.10.8.3 Conditional feature macros

  

__ STDC_NO_VLA__
      整数常量1,用于表示实现不支持可变长度数组或可变   修改后的类型。

我个人不使用VLA,因为如果阵列大小相当大,则无法轻易找到分配失败。 E.g。

__STDC_NO_VLA__

在上面的片段中,如果size_t size = 8*1024; int arr[size]; 分配失败,那么直到运行时才会知道它。什么是&#34;足够小&#34;内存分配与平台相关的大小。因此,在一台机器上,1MB的分配可能会成功,另一台可能会失败,更糟糕的是,没有办法解决这个问题。

因此,VLA的使用受到限制,并且只能用于您知道在给定平台上始终成功的小型阵列。但是我会简单地对数组大小进行硬编码并处理边界条件。

答案 1 :(得分:1)

也许使用枚举来定义a的值。

enum { a = 5 };
int arr [a];

也许这不是枚举的意图,但枚举成员是最接近C中常量的东西。与使用#define定义所有内容的常见做法不同,a的可见性是受范围限制,此处与arr相同。

答案 2 :(得分:0)

const - 限定变量与常量表达式不同;常量表达式在编译时已知其值,而const - 限定变量(通常)不会(尽管看起来应该如此)。

请注意,在C99及更高版本中,可以声明可变长度数组,其中直到运行时才知道数组大小。您必须使用C99或更高版本的编译器,并且鉴于该功能在2011标准中是可选的,您必须检查功能宏以查看是否有可用的VLA:

static const int a = 10; // a is not a constant expression

#if defined( __STDC__ ) && defined ( __STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L && !defined( __STDC_NO_VLA__ ) 
/**
 * VLAs are available in this environment
 */
#define USE_VLA 1
#endif

#ifdef USE_VLA
   int arr[a];
#else
  /**
   * VLAs are not available, either because it's a pre-1999 implementation,
   * or it's a post-2011 implementation that does not support optional
   * VLAs.  We'll have to use dynamic memory allocation here, meaning we'll
   * also need an explicit free call when we're done with arr 
   */
  int *arr = malloc( sizeof *arr * a );
#endif
...
  do_something_interesting_with( a );
...
#ifndef USE_VLA
  free( a );
#endif

至少在最近,微软的C编译器不支持VLA。但是,他们一直在添加一些C99功能,例如混合声明和代码,因此最新版本可能支持VLA。我不知道。