В 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-составители.
Возможный дубликат [неверное преобразование из 'void \ *' в 'node \ *' \ [-fpermissive \]] (http://stackoverflow.com/questions/16793587/invalid-conversion-from-void-to -node-fpermissive) –
Я не думаю, что сообщение об ошибке было 'void не может использоваться для инициализации kiss_fft_ctx'. Я думаю, что это были 'void *' и 'kss_fft_ctx *'. Эти звездочки делают ** BIG ** разницу в значении и понимании языка. – abelenky