2016-08-20 79 views
-1

我想在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 ; 

我把“常量”在INT面前,然后我得到了另一个错误“C2166:左值指定const对象”。 我如何使它无错误?

(PS,这是一个开放的源代码,所以不应该有任何错误。这不是一个问题,但我只是想知道为什么。)

+2

在上面的误差,*预期常量表达式*不*** *** NOT意味着'const int的x'。它表示一个常量表达式,其值在编译时已知,如'#define ilen 199030'和'#define olen 1000'或'enum {olen = 1000,ilen = 199030}' –

+2

代码是正确的。它不是你的编译器。 MSVC不支持C标准的17岁特性,例如VLA。使用符合现代标准的编译器,如gcc或clang。 – Olaf

+0

@David C. Rankin这就是我想要的。现在它工作正常。我把这两个常量大写,表明它们是不可改变的。请让你的评论一个答案。非常感谢! – IanHacker

回答

0

继续评论,您遗漏的微妙之处在于,在C中,数组声明需要常量表达式用于数组大小(例如array[CONST])。 fn1。当你声明:

int ilen = 199030, olen = 1000, error ; 

无论ilenolen常量表达式。 (最简单的方式去思考它,你可以很容易地做到ilen = ilen + 2; - 所以ilen不是常量表达式

常量表达式通常是由宏观与#defineenum(其中创建全局常量)创建的。 (并且你通常使用CAPITALIZE常量 - 只是为了与其他变量区分开来)。所以,你可以这样做:

#define ILEN 199030 
#defile OLEN 1000 

enum { OLEN = 1000, ILEN = 199030 }; 

,然后宣布你float阵列:

float in [ILEN], 
    out [OLEN]; 

FN 1.现代的C编译器允许允许使用的可变长度数组可以在t中声明他是你尝试的方式,但正如其他人指出的那样,你的编译器不支持VLA。

+0

解决你的答案。这是最快最准确的答案。所以我给你这个观点。非常感谢! – IanHacker

+0

很高兴我能帮到你。还有其他很好的答案,也许我只是在我的回答中更长时间了:):' –

+0

对不起,但这个答案是错误的。 C支持自C99以来的可变长度数组(它们使得C11成为可选的,但是任何现代编译器都支持它们,因为它也支持C99) – Olaf

6

的Visual Studio不支持可变长度阵列。

艾朗定义该数组的大小不是恒定的表达式(从这里开始被描述为:常数)的变量和厄伦,所以以下是可变长度数组:

float in [ilen] ; 
float out [olen] ; 

值199030和1000是常量,因此以下仅为常规数组:

float in [199030] ; 
float out [1000] ; 

定义具有const限定符的对象不会使对象成为常量。

您可以使用#define将值定义为宏,但这与手动编写常量相同,因为在编译代码之前将定义的宏替换为它们表示的值。编译开始之前前

int array[1000]; 

#define ILEN 1000 
int array[ILEN]; 

转换为。

当然,您应该使用#define,因为它更方便且不易出错。

+0

我明白你的观点。正如奥拉夫所说,如果我使用gcc或clang,我不会有这样的错误。谢谢你的解释。 – IanHacker

+0

@IanHacker查看更新。 – 2501

+0

恐怕你在第一版中没有提到#define。那就是我真正想要的。我也已经提出了你的答案。再次感谢您的解释。 – IanHacker

-2

至少在C89中,数组的大小必须是一个costant表达式。 costant表达式的值不会更改。下面是常量表达式的几个例子:

#define SIZE (200) 
... 
int v[200];/* Ok*/ 
int w[200 + 1]; /*Ok because 200 + 1 does always 201*/ 
int y[SIZE]; /* Better*/ 
... 

这意味着你不能使用variabile的指定数组的大小,即使您使用“常量”关键字声明,是因为通过利用一个常量的值,你扇变化值的指针。

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*/ 

要验证常量的值是可以改变的,试试这个:

#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标准引入了VLAs(Variable Lenghts Arrays)和许多其他可怕特性。使用-std = c99标志(或者与非GCC兼容的编译器相同),可以使用变量来指定数组的大小,但这是一个不好的事情,因为它隐藏了对malloc的调用。 C99扩展基本上是由GCC和Numerical C引入的,现在许多编译器拒绝了C99标准的某些特征。 Visual Studio的编译器不支持-rightly- VLA,所以你有两个选择: - 使用malloc - 避免动态内存(推荐)

在严重的环境中的malloc是不是一种选择,因为它是严格按照这样的标准严格禁止作为MISRA/C和NASA子集。但即使在“不那么关键”的环境中,避免使用malloc也是一种好的做法,因为它可以让你更容易编写可预测和无缺陷的代码,因为你不必担心内存泄漏,忘记free()等。解决方案就是在程序开始时分配大量内存,并在需要时使用它。

综上所述声明一个阵列最好的方法是:

#define SIZE (...) 
... 
int v[SIZE]; 
... 
+0

不是我的倒票,但是...使用VLA并不隐藏对'malloc()'的调用;数组不是被动态分配的,VLA并不是无条件的坏事实际上,它们是非常有用的。大小不检查,然后你可能会遇到问题,但C为您提供了许多其他减少自己喉咙的方法,许多人利用其中的许多方法 - 具有可预测的结果。仅仅因为工具是危险的并不意味着它不应该存在;这意味着它应该谨慎使用。尽管有些地方禁止使用malloc()等,但这不是C代码的一般性。 –

+0

调用未定义的行为并不能证明任何事情。关于'malloc'等部分是无稽之谈。在C++中,你也会禁止使用标准库的主要部分,'new'等。在Python中是一样的吗?与固定长度数组相比,VLA与'malloc'没有更多的关系。在**嵌入式软件中不使用动态内存分配**有其他原因,最显着的是运行时间和内存分配的可预测性。许多这种系统使用例如pool,它们实际上分享了你用'malloc'和朋友编写的问题(它们很容易被MISRA所接受)。 – Olaf