Malloc работает с int, но не со строками

Я очень новичок в языке 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]

Извините за мой плохой английский, это не мой родной язык. Еще раз спасибо.

Подсказка: *string = "Hello World!"; это не то, как вы это делаете. Смотрите: strcpy().

tadman 10.01.2023 20:16

Совет: вам нужно освежить в памяти, что можно и что нельзя копировать с помощью * разыменования. int* — тривиальная копия, и char* сработает, если вы копируете один char.

tadman 10.01.2023 20:17

Дополнительные подсказки: «Привет, мир!» не помещается в 2 байта

David Ranieri 10.01.2023 20:17

Выполнение *string возвращает первое char из string, но printf требуется char * вместо %s. Итак, вы хотите: printf("%s",string); Но ваш malloc выделяет место только для одного байта — недостаточно места для строки, которой требуется место для терминатора EOS (0x00). TL; DR: отказаться от malloc и изменить *string = "Hello World!" --> string = strdup("Hello World!");

Craig Estey 10.01.2023 20:20

Вы можете / должны искать документацию для 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; }

Craig Estey 10.01.2023 20:28
sizeof(char) определяется как 1 - всегда!
Ted Lyngmo 10.01.2023 20:41
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Laravel - это мощный PHP-фреймворк, используемый для создания масштабируемых и надежных веб-приложений. Одним из преимуществ Laravel является его...
Что такое двойные вопросительные знаки (??) в JavaScript?
Что такое двойные вопросительные знаки (??) в JavaScript?
Как безопасно обрабатывать неопределенные и нулевые значения в коде с помощью Nullish Coalescing
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание API-ресурса Laravel может быть непростой задачей. Она требует глубокого понимания возможностей Laravel и лучших практик, чтобы обеспечить...
Как сделать компонент справочного центра с помощью TailwindCSS
Как сделать компонент справочного центра с помощью TailwindCSS
Справочный центр - это веб-сайт, где клиенты могут найти ответы на свои вопросы и решения своих проблем. Созданный для решения многих распространенных...
Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Отказ от ответственности: Эта статья предназначена только для демонстрации и не должна использоваться в качестве инвестиционного совета.
0
6
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Заявление;

char* string = (char*)malloc(sizeof(char)+1);

Выделяет память только для 2 байт.


Затем:

*string = "Hello World!";

Не копирует строковый литерал "Hello World! в string.

Стандартная библиотека C предоставляет strcpy для копирования двух строк. Вы также можете использовать POSIX strdup.


Неправильный аргумент для printf:

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 );
}
 

Другие вопросы по теме