Подтвердить что ты не робот

Почему С++ требует приведения для malloc(), но C нет?

Мне всегда было интересно об этом - зачем в С++ мне нужно вернуть возвращаемое значение из malloc, но не в C?

Вот пример в С++, который работает:

int *int_ptr = (int *)malloc(sizeof(int*));

И вот пример в С++, который не работает (без приведения):

int *int_ptr = malloc(sizeof(int*));

Я слышал, что в C, фактически, вывод результата из malloc() является ошибкой.

Кто-нибудь может прокомментировать эту тему?

4b9b3361

Ответ 1

Несколько точек:

C позволяет void-указатели быть неявно преобразованными в любой другой тип указателя объекта. С++ - нет.

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

Если вы пишете С++, вы должны использовать new и delete вместо malloc() и free(). Да, да, я слышал все причины, по которым люди хотят, чтобы их код был скомпилирован как C и С++, но преимущества использования правильного инструмента управления памятью для языка перевешивают стоимость поддержки двух версий IMO.

Примечание: тип void * был добавлен в стандарт C89; более ранние версии C имели malloc() return char *, поэтому в этих версиях приведение было необходимо, если вы назначали результат другому типу указателя. Практически все поддерживают хотя бы стандарт C89, поэтому вероятность того, что вы столкнетесь с одной из старых версий, очень-очень низкая.

Ответ 2

Это потому, что С++ - это строго типизированный язык. В С++ неявные приведения допускаются только в том случае, если они "расширяются", то есть если новый тип может содержать каждое значение, которое может хранить старый тип. Допускается литье из меньшего целочисленного типа в более крупный целочисленный тип; допускается использование от любого типа указателя до void*; допускается литье из подкласса в его суперкласс. Все остальные роли должны быть сделаны явно, тем самым сообщая компилятору "Я знаю, что я делаю, это не ошибка".

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

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

Ответ 3

C поддерживает неявное преобразование из void* в другие типы указателей. С++ запрещает его.

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