Я очень новичок в языке C. Я пытаюсь узнать о распределении памяти на следующих примерах.
Если я выделяю память для целого числа следующим образом:
int* pint = (int*)malloc(sizeof(int));
if (pint == NULL) {
printf("NULL pointer!");
} else {
*pint = 5;
printf("el valor es: %d", *pint);
free(pint);
}
Это отлично показывает число 5, и память освобождается правильно
Но если я попытаюсь сделать то же самое с такой строкой:
char* string = (char*)malloc(sizeof(char)+1);
if (string == NULL) {
printf("NULL pointer!");
} else {
*string = "Hello World!";
printf("%s", *string);
free(string);
}
Почему это происходит и как я могу это исправить?
Заранее спасибо
РЕДАКТИРОВАТЬ
Извините, я забыл показать ошибку, которую выдает компилятор c, моя ошибка.
Ошибка:
Предупреждение: присваивание 'char' из 'char *' делает указатель целочисленным без приведения [-Wint-conversion]
Извините за мой плохой английский, это не мой родной язык. Еще раз спасибо.
Совет: вам нужно освежить в памяти, что можно и что нельзя копировать с помощью * разыменования. int* — тривиальная копия, и char* сработает, если вы копируете один char.
Дополнительные подсказки: «Привет, мир!» не помещается в 2 байта
Выполнение *string возвращает первое char из string, но printf требуется char * вместо %s. Итак, вы хотите: printf("%s",string); Но ваш malloc выделяет место только для одного байта — недостаточно места для строки, которой требуется место для терминатора EOS (0x00). TL; DR: отказаться от malloc и изменить *string = "Hello World!" --> string = strdup("Hello World!");
Вы можете / должны искать документацию для strdup. Но код, который вам понадобится, похож на него. Вот простой пример: char * strdup(const char *str) { size_t len = strlen(str) + 1; char *dup = malloc(len); if (dup != NULL) memcpy(dup,str,len); return dup; }
sizeof(char)
определяется как 1
- всегда!
Заявление;
char* string = (char*)malloc(sizeof(char)+1);
Выделяет память только для 2 байт.
Затем:
*string = "Hello World!";
Не копирует строковый литерал "Hello World! в string.
Стандартная библиотека C предоставляет strcpy для копирования двух строк. Вы также можете использовать POSIX strdup.
printf("%s", *string);
%s спецификатор формата ожидает char *, *string выдает char.
Измените его на:
printf("%s", string);
В сторону: преобразование результата malloc и семейства является излишним и может скрыть ошибку. Эти функции возвращают void *, который автоматически преобразуется в правильный тип.
Для начала это выделение памяти
char* string = (char*)malloc(sizeof(char)+1);
Не имеет смысла.
Здесь выделено всего 2 байта, потому что sizeof( char ) всегда равно 1.
Если вы хотите выделить массив, в котором будет храниться строка "Hello World!", вам следует написать, например
char *string = malloc( sizeof( "Hello World!" ) );
В этом заявлении
*string = "Hello World!";
Указатель string разыменован. Таким образом, левый операнд оператора присваивания (выражение *string эквивалентно выражению string[0]) имеет тип char, а правый операнд имеет тип char[13] (строковые литералы имеют типы массивов символов), который неявно преобразуется в указатель на первый элемент строкового литерала типа char *.
Итак, в этом операторе присваивания вы пытаетесь присвоить указатель символу. Компилятор должен выдать сообщение для этого оператора, потому что нет неявного преобразования указателей в символы.
Также в этом вызове printf
printf("%s", *string);
Вы пытаетесь вывести один символ *string как целую строку, используя спецификатор преобразования %s, что приводит к неопределенному поведению.
Вместо этого утверждения
*string = "Hello World!";
Можно написать например
string = "Hello World!";
Теперь указатель string указывает на строковый литерал. А если ты напишешь
printf("%s", string);
Тогда действительно будет выведен строковый литерал.
Но это приводит к утечке памяти, потому что в этом случае будет потерян адрес ранее выделенной памяти.
Для копирования содержимого строкового литерала следует использовать стандартную строковую функцию strcpy, объявленную в заголовке <string.h>. Например
char *string = malloc( sizeof( "Hello World!" ) );
if ( string != NULL )
{
strcpy( string, "Hello World!" );
printf( "%s\n", string ); // or just puts( string );
}
Подсказка: *string = "Hello World!"; это не то, как вы это делаете. Смотрите: strcpy().