Почему C ++ требует приведения для malloc (), а C - нет? - PullRequest
38 голосов
/ 13 августа 2010

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

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

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

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

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

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

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

Ответы [ 3 ]

32 голосов
/ 13 августа 2010

Несколько баллов:

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

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

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

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

13 голосов
/ 13 августа 2010

Это потому, что C ++ является языком со строгой типизацией.В C ++ неявное приведение разрешено только в том случае, если оно «расширяется», то есть если новый тип может содержать каждое значение, которое может содержать старый тип.Разрешается приведение от целочисленного типа к целочисленному типу;разрешено приведение от любого типа указателя к void*;приведение из подкласса к его суперклассу разрешено.Все остальные приведения должны быть сделаны явно, тем самым говоря компилятору: «Я знаю, что я делаю, это не ошибка».

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

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

9 голосов
/ 13 августа 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...