2013-08-04 3 views
5

я следующий код в заголовке CтаНос ошибка в STRUCT (C)

typedef struct { 
    kiss_fft_scalar r; 
    kiss_fft_scalar i; 
} kiss_fft_cpx; 

И я осуществил следующий код в тестовой программе

kiss_fft_cpx *fin = malloc(4*sizeof(kiss_fft_cpx)); 

И это дало мне сообщение об ошибке : «Значение типа void не может использоваться для инициализации объекта типа« kiss_fft_ctx ».

Я использую Visual Studio C/C++ проект консоли win32.

Может ли кто-нибудь сказать мне, как правильно использовать malloc здесь? Благодаря!

+0

Возможный дубликат [неверное преобразование из 'void \ *' в 'node \ *' \ [-fpermissive \]] (http://stackoverflow.com/questions/16793587/invalid-conversion-from-void-to -node-fpermissive) –

+1

Я не думаю, что сообщение об ошибке было 'void не может использоваться для инициализации kiss_fft_ctx'. Я думаю, что это были 'void *' и 'kss_fft_ctx *'. Эти звездочки делают ** BIG ** разницу в значении и понимании языка. – abelenky

ответ

12

Вы должны бросить возвращаемый тип, как это:

kiss_fft_cpx *fin = (kiss_fft_cpx*) malloc(4*sizeof(kiss_fft_cpx)); 

, но подразумевается, что вы компиляции кода как C++, а не C, потому что это C++ ошибка, а не ошибка C. Возможно, вам захочется проверить расширение вашего файла и/или параметры вашего компилятора.

Если вы действительно являются с помощью C++, вы должны при минимальном использовании new вместо malloc:

kiss_fft_cpx *fin = new kiss_fft_cpx[4]; 

и идеально переосмыслить, нужно ли создавать объекты динамически, как это - не могли бы вы быть с помощью std::vector или подобный вместо этого?

+2

+1 для заметки о C++. –

+0

Прохладный, проблема в том, что я должен использовать код C, запрограммированный другими в моем проекте на C++. Итак, мне интересно, возможно ли использовать другую схему, а не malloc, чтобы закончить выделение памяти. (В противном случае C++ кажется довольно глупым здесь, когда мы используем C в C++). – Cancan

+4

@Cancan Это, но вам лучше не делать этого. Просто скомпилируйте вместо C. ** Не пытайтесь скомпилировать код C как C++. ** Это разные языки. –

3

В C вы можете наложить указатель на пустоту, возвращенный malloc. C делает это для вас, но вы также можете быть явным.

malloc возвращает void * или указатель void, это возвращаемое значение затем может быть передано программистом в другие типы указателей. Или программист может полагаться на C, чтобы преобразовать тип. Ожидается, что изменение типа C с использованием отбросов не изменится.

Однако код C, который опирается на C-компилятор, может быть затруднен и затруднен для чтения. Программист-программист может помочь программистам-программистам, которые в конечном итоге должны будут прочитать код.

Добавление явного перевода в возвращаемое значение malloc помогает людям, у которых будет , прочитать код и определить намерения автора. Это реальная выгода от явного литья указателя void, возвращаемого malloc. Эта практика программирования Неправильно направьте компилятор или воспользуйтесь некоторой функцией тайного компилятора, которая может измениться.

Следующие три примера подчеркивают эту практику программирования. В первом примере malloc (который определен в <stdlib.h>) явно литой, и выполняется некоторая тривиальная работа .

#include <stdlib.h> 
    #define nr_chars 4 
    main() 
    { 
    char *data; 

    data = (char *) malloc(nr_chars*sizeof(char)); 

    *data++ = 'a'; 
    *data++ = 'b'; 
    *data++ = 'c'; 
    *data++ = '\0'; // it is allowed to go one past an array 

    data -= nr_chars; // back to the front of data 

    printf("%s\n", data); 
    // prints abc at the console 

    } 

В этом втором примере, с той лишь разницей, что <stdlib.h> закомментирована. Код все еще работает и дает тот же результат. Теперь «почему» почему это работает довольно прямо. Когда C не находит прототип для функции, он предполагает, что функция возвращает int, но malloc возвращает указатель на пустоту.В этом случае явный листинг сказал компилятору C, а также углеродному блоку источника, что значение, возвращаемое malloc, должно быть преобразовано в указатель символа.

//#include <stdlib.h> 
    #define nr_chars 4 
    main() 
    { 
    char *data; 

    data = (char *) malloc(nr_chars*sizeof(char)); 

    *data++ = 'a'; 
    *data++ = 'b'; 
    *data++ = 'c'; 
    *data++ = '\0'; // it is allowed to go one past an array 

    data -= nr_chars; // back to the front of data 

    printf("%s\n", data); 
    // prints abc at the console 

    } 

Конечный (да) пример не выдает бросок и не включает в себя <stdlib.h>. И редактор Eclipse, и компилятор жалуются на этот код (как и должны). Сообщение компилятор

..\main.c(18) : warning C4047: '=' : 'char *' differs in levels of indirection from 'int' 

И исходный код:

//#include <stdlib.h> 
    #define nr_chars 4 
    main() 
    { 
    char *data; 

    data = malloc(nr_chars*sizeof(char)); 

    *data++ = 'a'; 
    *data++ = 'b'; 
    *data++ = 'c'; 
    *data++ = '\0'; // it is allowed to go one past an array 

    data -= nr_chars; // back to the front of data 

    printf("%s\n", data); 
    // compiler displays a "warning" and prints abc at the console 

    } 

Изменение пример 3 включить результаты без каких-либо предупреждений, и программа работает как задумано. Тем не менее, в обоих примерах 2 и 3 нет явного приведения и за время жизни кода, написанного в этом стиле, такой код будет более дорогим и, скорее всего, изменяться неправильно людьми (таким образом, дополнительными расходами), чем явным, используя приведения, которые поддерживаются C-составители.

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