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

#include <stdio.h>
#include <stdlib.h>

int main() {
    void *malloc(size_t size);
    char *ptr, *retval;
    ptr = (char *)calloc(10, sizeof(char));

    if (ptr == NULL)
        printf("calloc failed\n");
    else
        printf("calloc successful\n");

    retval = realloc(ptr, 5);

    if (retval == NULL)
        printf("realloc failed\n");
    else
        printf("realloc successful\n");

    free(ptr);
    free(retval);
}

вот мой код ошибка возникает в строке 14, там написано

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


c c++
person ejaz dogar    schedule 21.05.2012    source источник
comment
Это не C++, поэтому не помечайте его как таковой.   -  person Xeo    schedule 21.05.2012
comment
Можете ли вы переформатировать это, чтобы оно читалось чище?   -  person octopusgrabbus    schedule 21.05.2012
comment
@Xeo: Если бы он компилировался как C, он бы не понял проблемы ... Так что C ++, вероятно, более подходит ...   -  person Goz    schedule 21.05.2012
comment
@Goz: Если бы он знал, что делает, он бы скомпилировал это как C. :P   -  person Xeo    schedule 21.05.2012
comment
@Xeo: Без сомнения;) ... но его проблема возникает из-за того, что он пишет код на C++ (осознает он это или нет) ... как таковой тег c++ более уместен, чем тег C (IMO и все такое)   -  person Goz    schedule 21.05.2012
comment
@jamesdlin: хорошо, что не забыли изменить номер строки;)   -  person Goz    schedule 21.05.2012
comment
Я вернул тег на C++, потому что это именно проблема C++, даже если код может быть скомпилирован как C.   -  person Oliver Charlesworth    schedule 21.05.2012
comment
Людям, воюющим за редактирование тегов: это, несомненно, вопрос о C++. Эта проблема может возникнуть только при компиляции как C++. Вопрос о том, следует ли также включать также тег C, является спорным (я бы склонялся к тому, чтобы оставить его, так как это подчеркивает важное различие между двумя языками), но тег C++ абсолютно применим.   -  person Adam Rosenfield    schedule 21.05.2012


Ответы (4)


Вы можете просто преобразовать результат realloc в (char*), как и в случае с malloc.

retval = (char*)realloc(ptr, 5);

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

Редактировать: Как правильно указывает softy, вы перераспределяете ptr и сохраняете местоположение указателя в retval, что означает, что ptr потенциально указывает на недопустимую память, и вы НЕ должны ее освобождать. В лучшем случае вы освобождаете одну и ту же память дважды, в худшем случае вы вызываете free для памяти, которая уже была освобождена (с помощью realloc). В любом случае это плохо (тм). Поскольку вы вызываете какое-то серьезное «неопределенное поведение».

person Goz    schedule 21.05.2012
comment
хорошо!! спасибо за ваши ответы. в любом случае, я это сделал :) и извините за теги, так как это был мой первый вопрос, поэтому я не знал, как их использовать;) все равно спасибо;) - person ejaz dogar; 21.05.2012
comment
@ejazdogar: Если вы нажмете на маленькую галочку под номером слева от моего поста, вы примете мой пост ;) - person Goz; 22.05.2012

Вы не можете освободить указатель дважды. Здесь retval и ptr оба указывают на одно и то же место, добавьте этот код и проверьте перед бесплатным вызовом:

printf("%p \n ",ptr);
printf("%p \n",retval);

Realloc уменьшился в размере, но расположение указателя осталось прежним. вы также можете попробовать это:

if(ptr == retval)

/* delete either ptr or retval - just for sake of this programm , Idealy you shouldnt free the the pointer like this as Rightly Suggested by **Goz** in C++/c*/

Просто чтобы заставить его работать. В противном случае он отлично компилируется gcc, но если вы запустите его, вы получите грязную трассировку стека, поскольку вы пытаетесь дважды освободить один и тот же указатель. Основной вызов break функцией распределения памяти может или не может назначать одно и то же указатель на него. Если вы увеличите размер, может быть на 30 или 50, это может дать вам другой указатель.

с уважением, Софти

person Raulp    schedule 21.05.2012
comment
У вас есть хорошая мысль, но после перераспределения вы абсолютно не должны освобождать ptr ... он либо указывает на то же место, что и retval, либо уже освобожден! - person Goz; 21.05.2012
comment
да, может, а может и нет, вот почему эта проверка эквивалентности ptr! - person Raulp; 21.05.2012
comment
но если они не равны (или даже если они равны), то вам не следует освобождать ptr... так что проверка эквивалентности несущественна... вызов free на ptr - это ожидаемая ошибка... - person Goz; 21.05.2012
comment
ralloc не нужно уменьшать пространство, он может вернуть совершенно другую память. if (retval != NULL) {ptr = retval;} - person Martin York; 22.05.2012

Другие отмечают, что ваш код C компилируется как код C++. Приведение не требуется в C, но требуется в C++. В С++ вы должны использовать векторы (или строки).

Вот несколько замечаний по вашему коду:

  1. Не объявляйте malloc повторно. Включение stdlib.h сделает это за вас. К счастью, вы успешно продублировали его объявление, поэтому оно только избыточно (и сбивает с толку кого-то еще, читающего код). Если вы ошиблись в объявлении, у вас неопределенное поведение.

  2. Не освобождайте 'ptr', если realloc выполнен успешно.

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

person Happy Green Kid Naps    schedule 21.05.2012

Если вы хотите, чтобы он компилировался, используйте компиляцию C. Похоже, вы используете компиляцию C++. Это допустимый C, но не действительный C++. В большинстве компиляторов использование расширения .c в нижнем регистре заставит компилятор автоматически использовать компиляцию C. .cpp вызовет компиляцию C++, также .C (верхний регистр) может вызвать компиляцию C++ (например, в gcc).

person Clifford    schedule 21.05.2012