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

Можете ли вы объяснить, как память ниже выделяется для хранения такой большой строки, хотя я даю размер malloc только одному байту

char **str;
int len = 1;
str = malloc(sizeof(char*)*len);//wont this allocate only one byte in heap?
str[0] = "This is a string";//this is more than one byte
printf("%s",str[0]);

я довольно запутался в том, как это работает.


person Meghana    schedule 08.07.2016    source источник
comment
Вы не выделяете 1 байт. Вы выделяете указатель - возможно, 4 или 8 байтов. Затем вы присваиваете его константной строке, которая уже существует в другом месте.   -  person Johnny Mopp    schedule 08.07.2016
comment
Как вы думаете, почему malloc() выделит только один байт?   -  person babon    schedule 08.07.2016
comment
Почему эта заведомо недействительная программа работает? В общем, такого рода вопросы непродуктивны. Читайте о неопределенном поведении. (Эта конкретная программа может быть или не быть недействительной).   -  person n. 1.8e9-where's-my-share m.    schedule 08.07.2016
comment
str[0] = "This is a string"; не делает физическую копию. Для копирования используйте функцию strcpy(...).   -  person Beka    schedule 08.07.2016


Ответы (2)


Вы не выделяете один байт.

Выражение sizeof(char*)*len можно упростить до sizeof (char *), то есть до размера указателя на символ. Обычно это 4 или 8.

Затем вы просто сохраняете там один указатель, значение строкового литерала "This is a string" - это адрес, по которому этот литерал появляется в памяти, так что это:

str[0] = "This is a string";

просто выполняет присваивание размера одного указателя str[0] (который является указателем), никакие символы не копируются. Ровно один указатель - это то, сколько места вы выделили, так что все работает хорошо.

person unwind    schedule 08.07.2016

Вы не выделяете то, что, по вашему мнению, выделяете.

Когда ты сказал

char **str;

это не переменная, которая может содержать одну строку. Это переменная, которая может содержать массив из нескольких строк.

Когда ты сказал

int len = 1;
str = malloc(sizeof(char*) * len);

вы настраиваете str для хранения одной строки. То есть в данном случае len подсчитывает количество строк, а не длину строки.

Тогда, когда вы говорите

str[0] = "This is a string";

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

char *p;
p = "This is a string";

Если вы хотите выделить память для всей строки и фактически скопировать всю строку, это может выглядеть так:

const char *string_to_copy = "This is a string";
str[0] = malloc(strlen(string_to_copy) + 1);     /* +1 for \0 */
if(str[0] == NULL) exit(1);
strcpy(str[0], string_to_copy);

И если вы хотите использовать str для хранения нескольких строк, это может выглядеть так:

len = 4;
str = malloc(sizeof(char*) * len);
if(str == NULL) exit(1);
str[0] = "This";
str[1] = "is";
str[2] = "a";
str[3] = "test.";
person Steve Summit    schedule 08.07.2016