Как передать символ* по значению C ?

#c #arrays #string #reference #char

Вопрос:

Я определил атрибут типа char* content , который принимает строку, содержащую даже похожие символы, таким образом, я не мог использовать этот string тип.

Проблема здесь, когда я пытался определить сеттера для контента, заключалась в следующем :

 void MyClass::setContent(char* content)
{
    if(this->contentLength!=0){
        if(this->content)
            free(this->content);
        this->content = (char*)malloc(this->contentLength);
        memset(this->content,0,this->contentLength);
        memcpy(this->content,content,this->contentLength);
    }
}
 

знание этого contentLength также является атрибутом MyClass .

Однако в другом стеке я определил функцию, которая возвращает объект MyClass как этот :

 MyClass myfunction(args) {
    MyClass myclass;
    /**
     *Do some stuff on myclass
     */
    return myclass;
}
 

с другой стороны, я определил это :

 MyClass element = myFunction(args);
 

И здесь я потерял содержимое, потому что оно всегда указывает на адрес myclass в первом стеке.

как я могу скопировать content его в новый объект element ?

Я работаю над C 98 этим , и ни одно решение c 11 не может быть реализовано.

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

1. Если у вас есть компилятор C 98, вы можете скомпилировать (из его исходного кода) недавний компилятор GCC (например, GCC 10 в начале 2021 года, а затем у вас на компьютере есть компилятор C 14 (и, конечно, вы можете использовать std::string и библиотеку строк

2. @BasileStarynkevitch, у меня нет выбора, кроме как использовать C 98. Я работаю во встроенной среде.

3. GCC может быть скомпилирован как кросс-компилятор для встроенных процессоров. См., например, » КОЛЕСНИЦА » и этот проект доклада . Для получения дополнительной информации напишите мне (на английском или французском языках) по адресу basile@starynkevitch.net

4. @BasileStarynkevitch, проблема в том, что content он содержит символы и символы, которые, насколько мне известно, не принимаются, если я использую строку, подобную .

5. Тот std::string принимает любые char , в том числе '' . C 98 или современный C . Но если нет std::string , то есть другая жизнеспособная альтернатива, лучшая, чем сырье char* std::vector<char> .

Ответ №1:

Я определил атрибут типа char* content, который принимает строку, содержащую даже похожие символы,

Вот в чем твоя проблема. Если вы передаете a char * — и, что еще хуже , используете его для управления динамически выделяемой памятью, возвращаемой malloc() , есть много вещей, которые могут пойти не так.

Просто передайте std::vector<char> вместо этого. Он отслеживает свою собственную длину, не заботится о том, сколько значений '' в нем содержится, и может динамически изменяться по мере необходимости. Например, вы могли бы затем переопределить

 void MyClass::setContent(const std::vector<char> amp;content)
{
    this->content = content;    // this will copy all of the characters
                                //  from content to this-content
                                //  and manage memory for you
}
 

Существует множество документации std::vector , доступной, например, на странице cppreference vector, которая объясняет, какие операции vector поддерживает a. До тех пор, пока вы потрудитесь правильно использовать его операции (это не бесплатно для всех) std::vector<char> , это облегчит вашу жизнь. Хотя std::vector между стандартами C произошли некоторые изменения, даже версия C 98 должна соответствовать вашим потребностям.

Ответ №2:

Как передать символ* по значению C ?

Так же, как и другие типы, передаются по значению: не используйте ссылочный параметр. Пример:

 void function_name(char*); // the pointer will be passed by value
 

как я могу скопировать элемент content в новый объект?

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

Если вы хотите сделать глубокую копию, вы можете выделить новый массив, указать новый указатель на это отдельное выделение и скопировать строку из старого массива.

Но это не обязательно то, как вы должны писать класс. Вместо этого вам следует использовать std::string member или std::vector<char> в зависимости от варианта использования.


строка, содержащая даже символы типа , таким образом, я не мог использовать этот string тип.

Непонятно, что вы под этим подразумеваете. Если вы пытаетесь сказать, что std::string не можете содержать нулевые символы-терминаторы, то вы ошибаетесь.


P.S. Избегайте использования malloc в C .

Ответ №3:

Видишь https://en.cppreference.com/w/cpp/language/copy_constructor Когда вы возвращаете объект по значению, для копирования вашего объекта вызывается конструктор копирования.

Если вы не создадите его вручную, будет создан конструктор копирования по умолчанию. Он просто копирует указатель, поэтому два указателя ссылаются на один и тот же массив.

Вы можете создать конструктор копирования вручную, как это:

 MyClass(const MyClassamp; other)
{
    this->contentLength = other.contentLength;
    this->content = (char*) malloc(this->contentLength);
    memcpy(this->content, other.content, this->contentLength);

    // Copy every other field manually here, if you have any.
}
 

Обновление:
Смотрите ответы Ээрики и Питера, чтобы узнать о лучших методах и о том, как избежать этой необходимости.