it-roy-ru.com

Я использую результат malloc?

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

int *sieve = malloc(sizeof(int) * length);

скорее, чем:

int *sieve = (int *) malloc(sizeof(int) * length);

Почему это так?

2250
Patrick McDonald

Нет; Вы не разыгрываете результат, так как:

  • В этом нет необходимости, поскольку void * автоматически и безопасно переводится в любой другой тип указателя в этом случае.
  • Это добавляет беспорядок в код, приведения не очень легко читаются (особенно если тип указателя длинный).
  • Это заставляет вас повторяться, что, как правило, плохо.
  • Он может скрыть ошибку, если вы забыли включить <stdlib.h>. Это может привести к сбоям (или, что еще хуже, , а не вызвать сбой до некоторой степени в совершенно другой части кода). Подумайте, что произойдет, если указатели и целые числа имеют разные размеры; тогда вы скрываете предупреждение путем приведения и можете потерять биты вашего возвращенного адреса. Примечание: начиная с C11 неявные функции ушли из C, и этот момент больше не актуален, поскольку нет автоматического предположения, что необъявленные функции возвращают int.

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

Также отметьте, как отмечают комментаторы, что вышесказанное говорит о прямом C, а не C++. Я очень твердо верю в C и C++ как отдельные языки.

Чтобы добавить, ваш код без необходимости повторяет информацию о типе (int), которая может вызвать ошибки. Лучше разыменовать указатель, используемый для хранения возвращаемого значения, чтобы "заблокировать" их вместе:

int *sieve = malloc(length * sizeof *sieve);

Это также перемещает length вперед, чтобы улучшить видимость, и удаляет лишние скобки с sizeof; они нужны только , когда аргумент является именем типа. Многие люди, кажется, не знают (или игнорируют) это, что делает их код более многословным. Помните: sizeof не является функцией! :)


Хотя перемещение length вперед может увеличить видимость в некоторых редких случаях, следует также обратить внимание на то, что в общем случае лучше написать выражение как:

int *sieve = malloc(sizeof *sieve * length);

Так как сохранение sizeof первым в этом случае гарантирует, что умножение выполняется по крайней мере с size_t математическим.

Сравните: malloc(sizeof *sieve * length * width) и malloc(length * width * sizeof *sieve) вторая может переполнить length * width, когда width и length меньшего типа, чем size_t.

2073
unwind

В C вам не нужно приводить возвращаемое значение malloc. Указатель на void, возвращаемый malloc, автоматически преобразуется в правильный тип. Однако, если вы хотите, чтобы ваш код компилировался с помощью компилятора C++, необходимо преобразование. Предпочтительной альтернативой среди сообщества является использование следующего:

int *sieve = malloc(sizeof *sieve * length);

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

Слепки плохие, как указали люди. Специально указатель отливок.

351
dirkgently

Вы делаете разыгрываете, потому что:

  • Это делает ваш код более переносимым между C и C++, и, как показывает опыт SO, многие программисты утверждают, что пишут на C, когда они действительно пишут на C++ (или C плюс локальные расширения компилятора).
  • В противном случае может скрыть ошибку: обратите внимание на все SO примеры путаницы, когда писать type * против type **.
  • Идея, что он не даст вам заметить, что вы не смогли #include пропустить соответствующий заголовочный файл лес для деревьев. Это то же самое, что сказать: "Не беспокойтесь о том, что вы не попросили компилятор жаловаться на то, что не видите прототипы - этот pesky stdlib.h - ДЕЙСТВИТЕЛЬНО важная вещь, которую нужно помнить!"
  • Вызывает дополнительная когнитивная перекрестная проверка. Он помещает (предполагаемый) желаемый тип прямо рядом с арифметикой, которую вы делаете для необработанного размера этой переменной. Могу поспорить, что вы могли бы провести исследование SO, которое показывает, что ошибки malloc() обнаруживаются намного быстрее, когда происходит приведение. Как и с утверждениями, аннотации, раскрывающие намерения, уменьшают количество ошибок.
  • Повторять себя так, чтобы машина могла это проверить, - это часто здорово идея. Фактически, это то, что является утверждением, и это использование приведения является утверждением. Утверждения по-прежнему являются наиболее общей техникой, которую мы используем для получения правильного кода, так как Тьюринг придумал эту идею много лет назад.
326
Ron Burk

Как уже говорилось, это не нужно для C, но для C++. Если вы думаете, что собираетесь скомпилировать свой код C с помощью компилятора C++, по каким-либо причинам вы можете вместо этого использовать макрос, например:

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

Таким образом, вы все еще можете написать это очень компактно:

int *sieve = NEW(int, 1);

и он скомпилируется для C и C++.

160
quinmars

Из Википедия :

Преимущества кастинга

  • Включение преобразования может позволить программе или функции на C компилироваться как C++.

  • Приведение допускает версии malloc до 1989 года, которые изначально возвращали char *.

  • Приведение может помочь разработчику выявить несоответствия в определении размера при изменении типа указателя назначения, особенно если указатель объявлен вдали от вызова malloc () (хотя современные компиляторы и статические анализаторы могут предупреждать о таком поведении, не требуя приведения).

Недостатки в кастинге

  • В соответствии со стандартом ANSI C приведение является избыточным.

  • Добавление приведения может скрыть неудачу при включении заголовка stdlib.h , в котором находится прототип для malloc. В отсутствие прототипа для malloc стандарт требует, чтобы компилятор C предполагал, что malloc возвращает int. Если нет приведения, выдается предупреждение, когда это целое число присваивается указателю; однако, с использованием приведения это предупреждение не выдается, скрывая ошибку. В некоторых архитектурах и моделях данных (таких как LP64 в 64-разрядных системах, где long и указатели являются 64-разрядными, а int - 32-разрядными), эта ошибка может фактически привести к неопределенному поведению, поскольку неявно объявленный malloc возвращает 32- битовое значение, тогда как фактически определенная функция возвращает 64-битное значение. В зависимости от соглашений о вызовах и расположения памяти это может привести к разрушению стека. Эта проблема с меньшей вероятностью останется незамеченной в современных компиляторах, поскольку они единообразно выдают предупреждения о том, что была использована необъявленная функция, поэтому предупреждение все равно будет появляться. Например, стандартное поведение GCC заключается в отображении предупреждения, которое гласит "несовместимое неявное объявление встроенной функции" независимо от того, присутствует ли приведение или нет.

  • Если тип указателя изменяется при его объявлении, может также потребоваться изменить все строки, где вызывается и преобразуется malloc.

Хотя malloc без приведения является предпочтительным методом, и большинство опытных программистов выбирают его , вы должны использовать все, что захотите, зная о проблемах.

т.е.: если вам нужно скомпилировать программу на C как C++ (хотя это отдельный язык), вы должны использовать malloc с приведением типов.

119
ashiquzzaman33

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

98
PaulJWilliams

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

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

Некоторые комментарии:

  • Пустой указатель может быть преобразован в/из любого другого типа указателя без явного приведения (C11 6.3.2.3 и 6.5.16.1).

  • Однако C++ не допускает неявное приведение между void* и другим типом указателя. Так что в C++ приведение было бы правильным. Но если вы программируете на C++, вы должны использовать new, а не malloc (). И вы никогда не должны компилировать код C, используя компилятор C++.

    Если вам нужно поддерживать C и C++ с одним и тем же исходным кодом, используйте переключатели компилятора, чтобы отметить различия. Не пытайтесь насытить оба языковых стандарта одним и тем же кодом, потому что они несовместимы.

  • Если компилятор C не может найти функцию, потому что вы забыли включить заголовок, вы получите сообщение об ошибке компилятора/компоновщика. Поэтому, если вы забыли включить <stdlib.h>, который не важен, вы не сможете создать свою программу.

  • На древних компиляторах, которые следуют версии стандарта, которой более 25 лет, забывание включать <stdlib.h> может привести к опасному поведению. Потому что в этом древнем стандарте функции без видимого прототипа неявно преобразовывали возвращаемый тип в int. Явное приведение результата из malloc могло бы скрыть эту ошибку.

    Но это действительно не проблема. Вы не используете компьютер 25 лет, так зачем вам использовать компилятор 25 лет?

90
Lundin

В C вы получаете неявное преобразование из void* в любой другой указатель (данных).

85
EFraim

Приведение значения, возвращенного функцией malloc(), теперь не является необходимым, но я хотел бы добавить один момент, который, кажется, никто не указал:

В древние времена, то есть до ANSI C предоставлял void * в качестве универсального типа указателей, char * - это тип для такого использования. В этом случае приведение может отключить предупреждения компилятора.

Ссылка: C FAQ

66
Yu Hao

Не обязательно приводить результаты malloc, так как он возвращает void*, а void* может указывать на любой тип данных.

49
user968000

Просто добавив мой опыт, изучая компьютерную инженерию, я вижу, что два или три профессора, которых я видел, пишу на C, всегда бросают malloc, однако тот, кого я спросил (с огромным резюме и пониманием C), сказал мне, что это абсолютно ненужно, но Раньше он был абсолютно конкретным и привел студентов к менталитету быть абсолютно конкретным. По сути, приведение ничего не изменит в том, как оно работает, оно выполняет именно то, что говорит, выделяет память, и приведение не влияет на это, вы получаете ту же память, и даже если вы приведете ее к чему-то другому по ошибке (и каким-то образом уклонитесь от компилятора ошибки) C будет обращаться к нему таким же образом.

Edit: Кастинг имеет определенную точку. Когда вы используете нотацию массива, сгенерированный код должен знать, сколько мест в памяти нужно продвинуть, чтобы достичь начала следующего элемента, это достигается путем приведения. Таким образом, вы знаете, что для двойника вы идете на 8 байтов вперед, а для целого - 4 и так далее. Таким образом, это не имеет никакого эффекта, если вы используете нотацию указателя, в нотации массива это становится необходимым.

48
user3079666

Вот что руководство GNU C Library говорит:

Вы можете сохранить результат malloc в любой переменной указателя без приведения, потому что ISO C автоматически преобразует тип void * в указатель другого типа при необходимости. Но приведение необходимо в контекстах, отличных от операторов присваивания или если вы хотите, чтобы ваш код выполнялся в традиционном C.

И действительно, стандарт ISO C11 (p347) говорит так:

Указатель, возвращаемый в случае успешного выделения, выравнивается соответствующим образом, чтобы его можно было присвоить указателю на любой тип объекта с фундаментальным требованием выравнивания, а затем использовать для доступа к такому объекту или массиву таких объектов в выделенном пространстве (до тех пор, пока пространство явно освобождено)

30
Slothworks

Указатель void является универсальным указателем, и C поддерживает неявное преобразование из типа указателя void в другие типы, поэтому нет необходимости явно указывать его типизацию.

Однако если вы хотите, чтобы один и тот же код работал идеально совместимым на платформе C++, которая не поддерживает неявное преобразование, вам необходимо выполнить приведение типов, так что все зависит от удобства использования.

29
Endeavour

Возвращаемый тип void *, который может быть приведен к нужному типу указателя данных, чтобы иметь возможность обращения к нему.

28
swaps

В языке C указатель void может быть назначен любому указателю, поэтому не следует использовать приведение типа. Если вы хотите "безопасное распределение типов", я могу порекомендовать следующие макро-функции, которые я всегда использую в своих проектах на C:

#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)

С этим на месте вы можете просто сказать

NEW_ARRAY(sieve, length);

Для нединамических массивов третий обязательный макрос функции

#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])

что делает циклы массива более безопасными и удобными:

int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}
26
August Karlstrom

Это зависит от языка программирования и компилятора. Если вы используете malloc в C, нет необходимости набирать его, так как он автоматически наберет cast. Однако если вы используете C++, вам следует набрать cast, потому что malloc вернет тип void*.

25
Jeyamaran

Люди привыкли к GCC и Clang испорчены. Там не все так хорошо.

Я был довольно напуган за эти годы потрясающе старыми компиляторами, которые я должен был использовать. Часто компании и менеджеры применяют ультраконсервативный подход к изменению компиляторов и даже не будут тестировать если новый компилятор (с лучшим соответствием стандартам и оптимизацией кода) будет работать в их системе. Практическая реальность для работающих разработчиков заключается в том, что когда вы пишете код, вам нужно охватить свои базы, и, к сожалению, приведение malloc - хорошая привычка, если вы не можете контролировать, какой компилятор может применяться к вашему коду.

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

Аргумент, что в нынешних стандартах это не нужно, вполне обоснован. Но этот аргумент опускает практические аспекты реального мира. Мы пишем код не в мире, управляемом исключительно стандартами дня, а практиками того, что я люблю называть "полем реальности местного управления". И это изгибается и искривляется больше, чем когда-либо было пространство-время. :-)

YMMV.

Я склонен думать о том, чтобы использовать malloc как оборонительную операцию. Не красиво, не идеально, но в целом безопасно. (Честно говоря, если вы не включили stdlib.h, то у вас способ больше проблем, чем при использовании malloc!).

15
StephenG

Я вставил приведение просто, чтобы показать неодобрение уродливой дыры в системе типов, которая позволяет скомпилировать код, такой как следующий фрагмент, без диагностики, даже если никакие преобразования не используются для плохого преобразования:

double d;
void *p = &d;
int *q = p;

Я хотел бы, чтобы этого не было (и это не существует в C++), и поэтому я разыграл. Это представляет мой вкус и мою политику программирования. Я не только разыгрываю указатель, но и эффективно, разыгрываю бюллетень и изгоняю демонов глупости . Если я не могу на самом деле изгнать глупость , то, по крайней мере, позвольте мне выразить желание сделать это жестом акция протеста.

На самом деле, хорошей практикой является использование malloc (и друзей) с функциями, которые возвращают unsigned char *, и в основном никогда не используют void * в вашем коде. Если вам нужен общий указатель на любой объект, используйте char * или unsigned char * и используйте приведение в обоих направлениях. Единственное расслабление, которое можно потворствовать, возможно, это использование таких функций, как memset и memcpy без приведения.

Что касается приведения типов и совместимости с C++, если вы пишете свой код так, чтобы он компилировался как на C, так и на C++ (в этом случае вы должны привести возвращая значение malloc при назначении его для чего-то отличного от void *), вы можете сделать очень полезную вещь для себя: вы можете использовать макросы для приведения, которые преобразуются в приведения в стиле C++ при компиляции как C++, но уменьшаются до приведения C при компиляции как C:

/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif

Если вы придерживаетесь этих макросов, то простой grep поиск в вашей кодовой базе для этих идентификаторов покажет вам, где находятся все ваши приведения, поэтому вы можете проверить, являются ли какие-либо из них неправильными.

Затем, в дальнейшем, если вы регулярно компилируете код с C++, он будет принудительно использовать соответствующее приведение. Например, если вы используете strip_qual просто для удаления const или volatile, но программа изменяется таким образом, что теперь происходит преобразование типов, вы получите диагностику, и вам придется использовать комбинацию приведений, чтобы получить желаемое преобразование.

Чтобы помочь вам придерживаться этих макросов, у компилятора GNU C++ (не C!) Есть прекрасная функция: дополнительная диагностика, которая создается для всех случаев приведения типов в стиле C.

 -Wold-style-cast (только C++ и Objective-C++) 
 Предупреждать, если в старом стиле (C-style) приведен тип, отличный от void 
 Внутри программа на C++. Приведения нового стиля (dynamic_cast, 
 Static_cast, reinterpret_cast и const_cast) менее уязвимы 
 К непреднамеренным эффектам и их гораздо легче найти. 

Если ваш код на C компилируется как C++, вы можете использовать эту опцию -Wold-style-cast, чтобы выяснить все вхождения синтаксиса приведения (type), которые могут проникнуть в код, и проследить за этими диагностиками, заменив его соответствующим выбором из перечисленных выше макросов ( или комбинация, если необходимо).

Такая обработка преобразований является единственным крупнейшим автономным техническим обоснованием для работы в "чистом C": комбинированный диалект C и C++, который, в свою очередь, технически оправдывает приведение возвращаемого значения malloc.

12
Kaz

Лучшее, что можно сделать при программировании на C, когда это возможно:

  1. Сделайте так, чтобы ваша программа компилировалась через компилятор C со всеми предупреждениями, включенными -Wall, и исправляла все ошибки и предупреждения
  2. Убедитесь, что нет переменных, объявленных как auto
  3. Затем скомпилируйте его, используя компилятор C++ с -Wall и -std=c++11. Исправьте все ошибки и предупреждения.
  4. Теперь снова скомпилируйте с использованием компилятора C. Ваша программа должна теперь скомпилироваться без предупреждения и содержать меньше ошибок.

Эта процедура позволяет вам использовать строгую проверку типов в C++, тем самым уменьшая количество ошибок. В частности, эта процедура заставляет вас включать stdlib.h или вы получите

malloc не было объявлено в этой области

а также вынуждает вас разыграть результат malloc, или вы получите

неверное преобразование из void* в T*

или каков ваш целевой тип.

Единственная выгода от написания на C вместо C++, которую я могу найти:

  1. C имеет хорошо определенный ABI
  2. C++ может генерировать больше кода [исключения, RTTI, шаблоны, время выполнения полиморфизм]

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

Для тех, кто считает строгие правила C++ неудобными, мы можем использовать функцию C++ 11 с выведенным типом

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...
12
user877329

Я предпочитаю сниматься, но не вручную. Мой любимый - использовать макросы g_new и g_new0 из glib. Если glib не используется, я бы добавил похожие макросы. Эти макросы уменьшают дублирование кода без ущерба для безопасности типов. Если вы ошиблись в типе, вы бы получили неявное приведение между не пустыми указателями, что вызвало бы предупреждение (ошибка в C++). Если вы забудете включить заголовок, который определяет g_new и g_new0, вы получите ошибку. g_new и g_new0 оба принимают одинаковые аргументы, в отличие от malloc, который принимает меньше аргументов, чем calloc. Просто добавьте 0, чтобы получить инициализированную нулями память. Код может быть скомпилирован с помощью компилятора C++ без изменений.

11
proski

Нет, вы не разыгрываете результат malloc().

В общем, вы не приводите к или из void *.

Типичная причина, по которой это не делается, заключается в том, что сбой #include <stdlib.h> может остаться незамеченным. Это уже давно не проблема, поскольку C99 сделал неявные объявления функций недопустимыми, поэтому, если ваш компилятор соответствует хотя бы C99, вы будете получить диагностическое сообщение.

Но есть гораздо более веская причина не вводить ненужные указатели:

В C приведение указателя почти всегда является ошибкой. Это из-за следующего правила (§6.5 p7 в N1570, последний черновик для C11):

Объект должен иметь свое сохраненное значение, доступное только через выражение lvalue, которое имеет один из следующих типов:
- тип, совместимый с эффективным типом объекта,
- квалифицированная версия типа, совместимого с эффективным типом объекта,
- тип, который является типом со знаком или без знака, соответствующим действующему типу объекта,
- тип, который является типом со знаком или без знака, соответствующим квалифицированной версии действующего типа объекта,
- агрегатный или объединенный тип, который включает в себя один из вышеупомянутых типов среди своих членов (включая, рекурсивно, член субагрегированного или автономного объединения), или
- тип персонажа.

Это также известно как правило строгого наложения имен . Таким образом, следующий код неопределенное поведение :

long x = 5;
double *p = (double *)&x;
double y = *p;

И, иногда удивительно, следующее также:

struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;

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

тЛ; др

В двух словах: поскольку в C любое появление приведения указателя должно поднять красный флаг для кода, требующего особого внимания, Вы никогда не должны писать ненужные приведения указателя.


Примечания стороны:

  • Есть случаи, когда вам необходимо преобразовать void *, например, если вы хотите напечатать указатель:

    int x = 5;
    printf("%p\n", (void *)&x);
    

    Приведение здесь необходимо, потому что printf() - это функция с переменным числом, поэтому неявные преобразования не работают.

  • В C++ ситуация иная. Приведение типов указателей является довольно распространенным (и правильным) при работе с объектами производных классов. Следовательно, имеет смысл, что в C++ преобразование в и из void * является не неявным. C++ имеет целый набор различных форм кастинга.

11
user2371524

Кастинг только для C++, а не для C. В случае, если вы используете компилятор C++, лучше поменяйте его на компилятор C.

10
user3949394

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

9
iec2011007

Указатель void является универсальным указателем, и C поддерживает неявное преобразование из типа указателя void в другие типы, поэтому нет необходимости явно указывать его типизацию.

Однако если вы хотите, чтобы один и тот же код работал идеально совместимым на платформе C++, которая не поддерживает неявное преобразование, вам необходимо выполнить приведение типов, так что все зависит от удобства использования.

6
dhana govindarajan
  1. Как уже говорилось, это не нужно для C, но для C++.

  2. Включение преобразования может позволить программе или функции на C компилироваться как C++.

  3. В C это не нужно, поскольку void * автоматически и безопасно переводится в любой другой тип указателя.

  4. Но если вы преобразуете это, он может скрыть ошибку, если вы забыли включить stdlib.h. Это может вызывать сбои (или, что еще хуже, не приводить к сбою, пока в какой-то совершенно другой части кода).

    Поскольку stdlib.h содержит прототип для malloc найдено. В отсутствие прототипа для malloc стандарт требует, чтобы компилятор C предполагал, что malloc возвращает int. Если нет приведения, выдается предупреждение, когда это целое число присваивается указателю; однако, с использованием приведения это предупреждение не выдается, скрывая ошибку.

6
Mohit

приведение malloc не нужно в C, но обязательно в C++.

Приведение не нужно в C из-за:

  • void * автоматически и безопасно повышается до любого другого типа указателя в случае C.
  • Он может скрыть ошибку, если вы забыли включить <stdlib.h>. Это может вызвать сбои.
  • Если указатели и целые числа имеют разный размер, тогда вы скрываете предупреждение путем приведения и можете потерять биты вашего возвращенного адреса.
  • Если тип указателя изменяется при его объявлении, может также потребоваться изменить все строки, где malloc вызывается и приводится.

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

3
Aashish