Создание указателя, передача указателя, передача адреса указателя

#c #pointers #char

#c #указатели #символ

Вопрос:

В чем разница между этими двумя кодами?

Может кто-нибудь объяснить мне, например: #1 do, #2 do, #3 do , пожалуйста?

У меня есть некоторые идеи, что делают эти коды, но я не уверен в этом.

 void test(char *msg) {
/*3*/    msg = new char[5];
}

int main() {
/*1*/    char *msg;
/*2*/    test(msg);
}

// I think
// #2 Pass the pointer
// #3 Allocates 5 bytes char in address where the pointer points
  
 void test(char **msg) {
/*3*/    *msg = new char[5];
}

int main() {
/*1*/    char *msg;
/*2*/    test(amp;msg);
}

// I think
// #2 Pass the address to the 4 bytes memory block where the pointer is stored
// #3 Allocates 5 bytes char to the previous 4 bytes   allocates new 1 byte
  

Большое спасибо!

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

1. Я бы предложил добавить строку std::cerr << static_cast<void *>(msg) << 'n'; прямо перед и сразу после вызова test() . Какие различия вы заметили? (Приведение к void* тому, чтобы вы видели, что хранится, msg а не символы, на которые msg указывает.)

Ответ №1:

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

Изменение указателя, переданного по значению функции, не влияет на указатель, который был передан функции.

Немного уменьшая пугающий характер вашего примера, мы получаем:

 void test(std::string msg) {
    msg = std::string("Hello World");
}

int main() {
    std::string msg;
    test(msg);
    std::cout << msg;  // is still an empty string !
}



void test(std::string* msg) {
    *msg = std::string("Hello World");
}

int main() {
    std::string msg;
    test(amp;msg);
    std::cout << msg;  // prints hello world
}
  

Разница между двумя примерами (моим и вашим) заключается в том, что один передается по значению, а другой передается по ссылке (через указатель).

Более того, в вашем коде (обе версии) происходит утечка памяти, потому что вы не удаляете массив символов, выделенный via new .

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

1. О, итак, я передаю указатель, но по значению, поэтому он создает 5 байт символа msg и msg является указателем, но он был создан в локальной области видимости с помощью функции, не так ли? Так что в main() нем без изменений. Разве это не утечка памяти? Я имею в виду мой первый код.

2. @JohnDoe есть два очень разных варианта вашего кода, по крайней мере, вам нужно сказать мне, о каком из них вы говорите

3. @JohnDoe да, это утечка памяти, просто заметил это и добавит примечание

Ответ №2:

Первый:

У меня есть листок бумаги с какими-то бессмысленными каракулями на нем.
Я копирую эти каракули на другой лист бумаги и вручаю его вам в качестве подарка.
Вы стираете каракули на своей собственной бумаге и записываете на ней свой адрес.
Как вы можете видеть, мой лист бумаги по-прежнему заполнен только каракулями, и я понятия не имею, где вы живете.

Второй:

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

(Короткая версия: присвоение параметру, не являющемуся ссылкой на функцию, не имеет никакого эффекта вне этой функции. В указателях нет ничего особенного.)