我正在尝试使用Windows10上的Visual Studio VC ++ 2015编译“libsamplerate.dll”,指的是:http://www.mega-nerd.com/SRC/win32.html。
然后,我收到以下错误:
termination_test.c
.\tests\termination_test.c(82): error C2057: expected constant expression
.\tests\termination_test.c(82): error C2466: cannot allocate an array of constant size 0
.\tests\termination_test.c(82): error C2133: 'in': unknown size
.\tests\termination_test.c(83): error C2057: expected constant expression
.\tests\termination_test.c(83): error C2466: cannot allocate an array of constant size 0
.\tests\termination_test.c(83): error C2133: 'out': unknown size
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\cl.exe"' : return code '0x2'
“termination_test.c”最初来自: http://www.mega-nerd.com/SRC/download.html 这是导致错误的函数:
static void
simple_test (int converter)
{
int ilen = 199030, olen = 1000, error ;
{
float in [ilen] ;
float out [olen] ;
double ratio = (1.0 * olen) / ilen ;
SRC_DATA src_data =
{ in, out,
ilen, olen,
0, 0, 0,
ratio
} ;
error = src_simple (&src_data, converter, 1) ;
if (error)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
} ;
return ;
} /* simple_test */
我只是将这两行修改为:
float in [199030] ;
float out [1000] ;
......然后,工作得很好。
然而,定义有什么问题?
int ilen = 199030, olen = 1000, error ;
我把'const'放在int前面,然后我得到了另一个错误“C2166:l-value指定const对象”。 如何让它没有错误?
(P.S。,这是一个开源代码,所以不应该有任何错误。这不是一个问题,但我只是想知道为什么。)
答案 0 :(得分:6)
Visual Studio不支持可变长度数组。
定义数组大小的变量ilen和olen不是常量表达式(从这里描述为:常量),因此以下是可变长度数组:
float in [ilen] ;
float out [olen] ;
值199030和1000是常量,因此以下只是常规数组:
float in [199030] ;
float out [1000] ;
使用const限定符定义对象不会使对象成为常量。
您可以使用#define
将值定义为宏,但这与手动编写常量相同,因为在使用它们表示的值编译代码之前替换定义的宏。
#define ILEN 1000
int array[ILEN];
转换为:
int array[1000];
在编译开始之前。
当然你应该使用#define
,因为它更方便,更不容易出错。
答案 1 :(得分:0)
继续评论,你遗漏的微妙之处在于,在C中,数组声明需要一个常量表达式来表示数组大小(例如array[CONST]
)。 fn1。 当您声明:
int ilen = 199030, olen = 1000, error ;
ilen
或olen
都不是常量表达式。 (考虑它的简单方法是你可以轻松地ilen = ilen + 2;
- 所以ilen
不是常量表达式。)
常量表达式通常由具有#define
或enum
(创建全局常量)的宏创建。 (而且你通常使用CAPITALIZE常量 - 只是为了区别于其他变量)。所以你可以这样做:
#define ILEN 199030
#defile OLEN 1000
或
enum { OLEN = 1000, ILEN = 199030 };
然后声明你的float
数组:
float in [ILEN],
out [OLEN];
fn 1。 现代C编译器允许允许使用可变长度数组,它可以按照您尝试的方式声明,但正如其他人所指出的,您的编译器不支持VLA。
答案 2 :(得分:-2)
数组的大小,至少在C89中,必须是一个常数表达式。 costant表达式是一个表达式,其值不会改变。以下是常量表达式的几个例子:
#define SIZE (200)
...
int v[200];/* Ok*/
int w[200 + 1]; /*Ok because 200 + 1 does always 201*/
int y[SIZE]; /* Better*/
...
这意味着你不能使用变量来指定数组大小,即使你使用“const”关键字声明它,因为你通过利用指针来改变const值的值。
int n = 10;
const int size = 10;
int v[n]; /* Wrong in C89 and non C99 fully compliant compilers!*/
int x[size]; /* Again, not valid because costant value != costant expression*/
要验证是否可以更改const值,请尝试以下操作:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const int a = 0;
int *p = &a;
printf("Now a is %d\n",a);
*p = 1;
printf("Now a is %d\n",a);
return EXIT_SUCCESS;
}
第一次调用printf后,您会看到一个值发生了变化。这种行为无论如何都依赖于编译器,实际上GCC允许你改变一个const值但clang却没有。这就是为什么你不能使用变量作为数组的大小。 C99标准引入了VLA(Variable Lenghts Arrays)和许多其他可怕的功能。使用-std = c99标志(或非GCC兼容编译器的等效标志),您可以使用变量来指定数组的大小,但这是一个错误要做的事情,因为它隐藏了对malloc的调用。 C99扩展基本上是在GCC和Numerical C的推动下推出的,现在许多编译器拒绝了C99标准的一些特性。 Visual Studio编译器不支持VLA,因此您有两个选择: - 使用malloc - 避免动态记忆(最好)
在严重的情况下,malloc不是一种选择,因为严格的标准,如MISRA / C和NASA子集严格禁止。但即使在“不那么关键”的环境中,避免使用malloc也是一种很好的做法,因为它使您更容易编写可预测且无错误的代码,因为您不必担心内存泄漏,忘记free()等。解决方案包括在程序的最开始分配一个大的内存池,并在需要时使用它。
总结声明数组的最佳方法是:
#define SIZE (...)
...
int v[SIZE];
...