定义有什么问题?

时间:2016-08-20 19:05:05

标签: c arrays

我正在尝试使用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。,这是一个开源代码,所以不应该有任何错误。这不是一个问题,但我只是想知道为什么。)

3 个答案:

答案 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 ;

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编译器允许允许使用可变长度数组,它可以按照您尝试的方式声明,但正如其他人所指出的,您的编译器不支持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];
...