1) Если я просто инициализирую указатель на символ и назначаю ему строку, где эта информация находится?В кучу?В стеке?Пример: char
*pointer = "Hello world";
Ни в стеке, ни в куче."Hello world"
- это строковый литерал , обычно создаваемый в сегменте rodata
(данные только для чтения) исполняемого файла.На самом деле, если вы не укажете иначе, компилятор может хранить только одну копию "Hello world"
, даже если вы назначите ее нескольким указателям.Хотя обычно указателям нельзя назначать строки, поскольку это строковый литерал 1012 *, вы фактически назначаете адрес самому литералу - единственная причина, которая работает.В противном случае, как отмечает P__J__, вы должны скопировать строки из одного местоположения в другое.
2) Я попытался использовать malloc
, чтобы инициализировать мой указатель на символ и использовать его позже, чтобы назначить ему строку,но я не могу скомпилировать, я получаю ошибку, что не так с этой логикой? вот что я пытаюсь сделать:
char *pointer = malloc(sizeof(char) * 12);
*pointer = "Hello world";
Вы смешиваетеяблоки и апельсины здесь.char *pointer = malloc (12);
выделяет хранилище для 12 символов (байтов), а затем присваивает начальный адрес для этого нового блока памяти pointer
в качестве значения.(помните, указатель - это просто обычная переменная, которая содержит адрес чего-то другого в качестве значения)
Для каждого выделения должна быть проверка , чтовызов выполнен успешно, или вам нужно будет обработать ошибку.Распределение может и не получится, а при неудаче malloc, calloc * realloc
все вернет NULL
.Таким образом, каждый раз, когда вы выделяете, вы
char *pointer = malloc(12); /* note: sizeof (char) is always 1 */
if (pointer == NULL) { /* you VALIDATE each allocation */
perror ("malloc-pointer");
return 1;
}
Продолжая описанный выше случай, вы выделили 12 байтов и присвоили начальный адрес для нового блока памяти pointer
.Затем вы необъяснимым образом разыменовываете pointer
(например, *pointer
, который теперь имеет тип char
) и пытаетесь назначить адрес строкового литерала в качестве этого символа.
*pointer = "Hello world"; /* (invalid conversion between pointer and `char`) */
То, что вы хотите сделать, это скопировать "Hello world"
в новый блок памяти, удерживаемый указателем.Для этого, поскольку вы уже знаете, что "Hello world"
- это 12 символов (включая нуль-заканчивающийся символ), вы можете просто:
memcpy (pointer, "Hello world", 12);
( примечание: если у вас уже есть длина, нет необходимости вызывать strcpy
и заставить его снова сканировать конец строки
Теперь ваш новый выделенный блок памяти содержит "Hello world"
и память является изменяемой, поэтому вы можете изменять любые символы, которые вам нравятся.
Поскольку вы выделили хранилище, вы можете free (pointer);
, когда эта память больше не используется.
В двух словах - это разница между назначением адреса строкового литерала указателю или выделением хранилища и назначением первого адреса в блоке нового хранилища указателю, а затем копированием всего, что вам нравитсяновый блок (пока вы остаетесь в выделенных границах выделенного блока памяти).
Просмотрите все и дайте мне знать, если у вас есть дополнительные вопросы.