Пустые указатели и динамическое выделение памяти

#c #memory-management

#c #управление памятью

Вопрос:

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

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

const char *strmalloc(const char *string);
char *user_input = NULL;

int main(void) {
    printf("Enter a sentence to find out the number of words: ");
    strmalloc(user_input);
    return 0;
}

const char *strmalloc(const char *string) {
    char *tmp = NULL;
    size_t size = 0, index = 0;
    int ch;

    while ((ch = getchar()) != 'n' amp;amp; ch != EOF) {
        if (size <= index) {
            size  = 1;
            tmp = realloc((char*)string, size);
        }
    }
}
 

Как вы, возможно, знаете, прототип функции realloc выглядит следующим образом:

 void *realloc(void *ptr, size_t size)
 

Когда я использую функцию realloc в цикле while в strmalloc() функции, я получаю предупреждение о том, что:

 Passing 'const char *' to parameter of type 'void *' discards qualifiers
 

Я понятия не имею, что это значит, но я знаю, что могу избавиться от этого с помощью приведения типов к char*

Однако я узнал, что я не должен использовать приведение типов только для предотвращения предупреждения. Я должен узнать, о чем предупреждает меня предупреждение, и решить, является ли приведение типов правильным. Но опять же, я знаю, что указатель на void принимает любой тип данных, и для его указания требуется приведение типов. Итак, мой вопрос в том, должен ли я сохранить типизацию в realloc() функции или избавиться от нее и сделать что-то еще.

Комментарии:

1. Квалификатор — это ключевое слово, такое как volatile или const , которое изменяет тип. Это помогает?

2. @JohnKugelman Спасибо, что ответили на эту часть вопроса, но у меня все еще есть главный вопрос без ответа. Если вы знаете ответ, пожалуйста, скажите мне. Спасибо!

3. Это приведет вас к правильному ответу. Вы правы, что хотите избежать удаления предупреждения. Есть лучшее решение, чем отбрасывание const .

4. @JohnKugelman, извините, я не думаю, что понимаю. Не могли бы вы сказать мне, к чему вы клоните?

5. Не отбрасывайте квалификацию const . remove_spaces Пример очень похож на ваш код.

Ответ №1:

const является определителем типа. В C и, возможно, во многих других языках программирования, const примененный к типу данных, указывает, что данные доступны только для чтения.

Передача ‘const char *’ в параметр типа ‘void *’ отбрасывает квалификаторы

Приведенная выше ошибка, которую вы получаете, потому что вы передаете const object параметру, которого нет const ( (void *) in realloc ), и предупреждаете вас о возможности изменения (отбрасывания) значений, указанных const char* string с помощью void* ptr , что сводит на нет всю цель объявления данных как const .

Но, глядя на пример, вы пытаетесь выделить память для char* string , и после выделения вы хотели бы что-то записать в эту память, если вы это сделаете const , как вы ожидаете, что она будет записана.

Таким образом, вам не нужно, чтобы вы char* string были const , и, следовательно, нет необходимости в приведении к char* in realloc .

Комментарии:

1. Спасибо @IrAM, вы правы в том, что не можете изменить const char *string значение. Я не знал, о чем я думал. Но спасибо!