2016-08-20 4 views
-1

Я пытаюсь скомпилировать «libsamplerate.dll» с Visual Studio VC++ 2015 на Windows10, ссылаясь на: 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 ; 

Я поставил «сопзЬ» перед междунар, то я получил другую ошибку «C2166: L-значение задает константный объект». Как я могу сделать это безошибочным?

(PS, Это является открытым исходным кодом, так что не должно быть никаких ошибок. Это не вопрос, но я просто удивляюсь, почему.)

+2

В приведенной выше ошибки * ожидается постоянное выражение * это *** НЕ *** значит 'константный Int x'. Это означает постоянное выражение, значение которого известно во время компиляции, например '#define ilen 199030' и' #define olen 1000' или 'enum {olen = 1000, ilen = 199030} '' –

+2

Код верен. Это ваш компилятор, которого нет. MSVC не поддерживает 17-летние функции стандарта C, такие как VLA. Используйте современный стандартный компилятор, такой как gcc или clang. – Olaf

+0

@David C. Rankin Вот что я хотел. Теперь он работает нормально. Я капитализировал эти две константы, чтобы показать, что они не изменяемы. Пожалуйста, сделайте свой комментарий ответом. Спасибо огромное! – IanHacker

ответ

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]; 

сноска 1. Современные компиляторы позволяют разрешить использование массив переменной длины, который может быть объявлен в t он, как вы пытались, но, как указывали другие, ваш компилятор не поддерживает VLA.

+0

Решенный по вашему ответу. Это был самый быстрый и точный ответ. Поэтому я даю вам точку. Спасибо огромное! – IanHacker

+0

Рад, что я мог помочь. Есть и другие хорошие ответы, возможно, я просто дольше наматывался в своем ответе ':)' –

+0

Извините, но этот ответ неверен. C поддерживает массив переменной длины с C99 (они сделали его необязательным с C11, но любой современный компилятор поддерживает их, так как он также поддерживает C99. – Olaf

6

Visual Studio не поддерживает переменную длину массивы.

Переменные Ilen и олен, которые определили размер массива не являются постоянными выражениями (здесь и далее описывается как: констант), поэтому следующие являются массивы переменной длины:

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

Ценности 199030 и 1000 являются константы, поэтому следующие только обычные массивы:

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

Определение объекта с константным спецификатором не сделать объект постоянным.

Вы можете использовать #define, чтобы определить свои значения как макросы, но это идентично написанию констант вручную, поскольку определенные макросы заменяются перед компиляцией кода со значениями, которые они обозначают.

#define ILEN 1000 
int array[ILEN]; 

преобразуется в:

int array[1000]; 

прежде чем компиляции начинается.

Конечно, вы должны использовать #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 введены VLA (массивы переменных длин) и многие другие функции. С флагом -std = c99 (или эквивалентом для компиляторов, не совместимых с GCC) вы можете использовать переменные для указания размера массива, но это значение bad, потому что оно скрывает вызов malloc. Расширения C99 были существенно введены в пользу GCC и Numerical C, и в настоящее время многие компиляторы отвергают некоторые особенности стандартов C99. Visual Studio компилятор не -rightly- поддержки VLA, поэтому у вас есть два варианта: - использование таНос - избежать динамической памяти (предпочтительнее)

В серьезных ситуациях таНос не вариант, так как это строго запрещено строгими стандартами таких как подмножество MISRA/C и NASA. Но даже в «не столь критической» среде избегание использования malloc является хорошей практикой, потому что вам легче писать предсказуемый и бесплатный код, поскольку вам не нужно беспокоиться об утечке памяти, забытых бесплатных() и т. Д. решение состоит в том, чтобы выделить большой пул памяти в самом начале программы и использовать ее, когда это необходимо.

Резюмируя лучший способ объявить массив является:

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

Не мой нисходящий голос, но ... Использование VLA не скрывает вызов 'malloc()'; массив не распределяется динамически. VLA не являются безусловно плохими, на самом деле они чрезвычайно полезны. размеры не проверяются, тогда вы может столкнуться с проблемами, но C предоставляет вам множество других способов сократить свое горло, и многие люди используют многие из них - с предсказуемыми результатами. Просто потому, что инструмент опасен, это не значит, что он не должен существовать; это означает, что его следует использовать с должной осторожностью. И хотя есть места, где 'malloc()' и др. Запрещены, это не общность кода C. –

+0

Вызов неопределенного поведения ничего не доказывает. Часть о 'malloc' и т. Д. - это нонсенс. В C++ вы также запретили бы использовать основные части стандартного библиотечного, «нового» и т. Д.? То же самое в Python? VLA больше не связаны с 'malloc', чем массивы с фиксированной длиной. Не использование динамического распределения памяти в ** встроенном программном обеспечении ** имеет другие причины, в первую очередь предсказуемость времени выполнения и распределения памяти. Многие такие системы используют, например,пулы, которые фактически разделяют проблемы, которые вы пишете с помощью 'malloc' & friends (они очень хорошо разрешены, например, MISRA). – Olaf

Смежные вопросы