#c #указатели #calloc #строковый_литерал
char * buf = (char*)calloc(0,0); buf = "vygbubinon"; printf("%s\n", buf); Выводится "vygbubinon". Хотя по идее памяти выделено недостаточно
Ответы
Ответ 1
Давайте последовательно рассмотрим предложения указанного вами фрагмента кода. В первом предложении char * buf = (char*)calloc(0,0); выделяется память нулевого размера. Согласно стандарту языка C (7.22.3 Memory management functions) If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object. То есть вы можете запрашивать выделение памяти нулевого размера, но результат будет зависеть от платформы, где компилируется и выполняется программа. Либо будет возвращено значение NULL, либо некоторый действительный адрес памяти, по которому однако вы не можете обращаться к объекту. Так что данное предложение корректно. Далее в следующем предложении независимо от того, каков был результат предыдущего предложения (либо NULL, либо некоторый действительный адрес) указатель buf переприсваивается, и получает адрес первого символа строкового литерала "vygbubinon". buf = "vygbubinon"; Строковые литералы имеют статическую память. Следовательно, указатель получает адрес первого символа данного строкового литерала, расположенного в статической области памяти. Память для строковых литералов резервируется компилятором на этапе компиляции. (Компиляторы обычно собирают все литералы, присутствующее в программе, в некоторый пул литералов.) Ничего некорректного в этом предложении нет. Единственная проблема, связанная с этим предложением состоит в том, что если в предыдущем предложении была выделена память, то вы уже не сможете ее удалить, так как адрес этой памяти за счет переприсвоения указателя был утерян. Произойдет утечка памяти, но никакой ошибки времени компиляции или времени выполнения не будет. Ну, и, наконец, в этом предложении выводится на консоль данный литерал. printf("%s\n", buf); Так что фрагмент кода совершенно корректный за исключением возможной утечки памяти, что представляет собой лишь логическую ошибку.Ответ 2
памяти выделено недостаточно Нет, достаточно. Вот этот код: buf = "vygbubinon"; не копирует строку в память, на которую указывает buf. Он всего лишь присваивает указателю buf адрес строки "vygbubinon", лежащей где-то в сегменте данных. Если будет понятней, то на уровень ниже это может выглядеть как-то так: .data ; ... _some_static_string db "vygbubinon", 0 buf dd ? ; ... .code ; ... mov buf, offset _some_static_string Если же вам нужно скопировать строку в область памяти, адрес которой содержится в указателе, нужно использовать функции семейств strcpy(), memcpy() и другие.Ответ 3
char *buf - всего-лишь переменная-указатель. По сути она является просто адресом некоторой ячейки памяти. В случае со строками - это адрес самого первого символа. Поэтому в первой строке вы присваиваете переменной buf адрес выделенной памяти, но никак не саму память. А в следующей строке присваиваете buf значение из области данных программы, т.е. ваше "vygbubinon". При этом следует учитывать, что если вы не освобождаете кусок памяти, выделенный в куче вызовом malloc (если вы выделяли не 0) и перезаписываете указатель на нее, то происходит утечка памяти
Комментариев нет:
Отправить комментарий