Calloc со структурой с указателями в C

Я знаю, что calloc запрашивает используемую память, записывает 0 во все биты, а затем возвращает указатель на нее.

Мой вопрос: если я использую calloc со структурой, содержащей указатели, будут ли эти указатели иметь значение NULL или мне нужно установить их так, чтобы они указывали на NULL?

struct a{
char * name;
void * p;
}* A;

Итак, будут ли name и p указывать на NULL после того, как я использовал calloc со структурой a?

Спасибо!


person Mihai Neacsu    schedule 02.05.2011    source источник


Ответы (3)


Почему-то вы получили много неправильных ответов. C не требует, чтобы нулевые указатели представлялись полностью нулевыми битами. Многие ошибочно думают, что это так, поскольку целочисленное константное выражение со значением 0, преобразованное в указатель, становится нулевым указателем.

С учетом сказанного, во всех реальных системах нулевые указатели являются полностью нулевыми битами, и calloc — вполне разумный способ получить массив указателей, инициализированных нулевым указателем в реальном мире.

person R.. GitHub STOP HELPING ICE    schedule 02.05.2011
comment
+1: единственный ответ, который я видел, даже близок к правильному. Я полагаю, что некоторые системы IBM и Unisys используют нулевые указатели, в которых не все биты равны нулю. Если на то пошло, x86 тоже может - значение сегмента 0 дает нулевой указатель, независимо от смещения. Все нулевые биты будут работать, но возможны и другие значения нулевого указателя. - person Jerry Coffin; 02.05.2011
comment
Просто потому, что некоторый ненулевой указатель сегмента: смещение может оцениваться так же, как нулевой линейный адрес, я бы не назвал его нулевым указателем. Компилятор C должен был бы сгенерировать код для выполнения дорогостоящей дополнительной работы по проверке нулевых указателей, если бы вы вызывали эти нулевые указатели, и это не улучшит качество реализации, поскольку только представление, созданное компилятором, нужно рассматривать как представление. нулевой указатель кодом, который он генерирует (нулевые указатели никогда не возникают из арифметики, только из константных выражений). - person R.. GitHub STOP HELPING ICE; 02.05.2011
comment
На самом деле единственные причины, которые я могу придумать, чтобы использовать не все нулевые биты для нулевого указателя: (1) если адрес 0 должен быть адресуемым, или (2) если вы хотите разыменование нулевого указателя для генерации ловушки, а адрес 0 не генерирует ловушку, а какой-то другой адрес генерирует. Всегда допустимо, независимо от аппаратного обеспечения, сделать реализацию C, в которой нулевые указатели являются нулевыми битами, и, таким образом, за исключением какой-либо убедительной причины не делать этого, разработчики должны всегда использовать все нулевые биты. биты как представление нулевого указателя. - person R.. GitHub STOP HELPING ICE; 02.05.2011
comment
@Р. Не так. Это не вопрос оценки одного и того же линейного адреса. Часть того, как Intel определяет защищенный режим, заключается в том, что сегмент 0 не может быть разыменован (с ним не связан никакой линейный адрес). Никакой дорогостоящей дополнительной работы не потребуется — нужно просто проверить часть сегмента и игнорировать смещение. - person Jerry Coffin; 02.05.2011
comment
@Р. Вы можете спорить о том, что все должно быть так, как вы хотите — это не изменит того, как обстоят дела на самом деле. - person Jerry Coffin; 02.05.2011
comment
@Jerry: я говорю о коде, который компилятор генерирует для if (ptr), а не о том, что должна делать машина. Это полностью зависит от компилятора, но поддержка нескольких псевдонимов для нулевого указателя будет огромной тратой времени и не принесет никаких преимуществ. - person R.. GitHub STOP HELPING ICE; 02.05.2011
comment
@Р. Прочитай, что я сказал. Компилятору нужно только протестировать сегмент, так что это не занимает никакого дополнительного времени. Да, у него могут быть преимущества — его использовали (в одном примере) для бесплатной передачи параметра обработчику исключений. - person Jerry Coffin; 02.05.2011
comment
Ваше утверждение о системах реального мира нуждается в оговорке, иначе оно будет неверным. Подробнее об экзотических указателях NULL на cfaq: c-faq.com/null/machexamp.html - person u0b34a0f6ae; 15.11.2011

Ответ R. хорош, но я хотел бы добавить стандартные кавычки, чтобы поддержать это, и показать способ значение 0 инициализирует вашу структуру, которая на самом деле дает указатели NULL.

Из N1548 (проект C11)

7.22.3.2 Функция calloc выделяет место для массива объектов nmemb, размер каждого из которых равен size. Пространство инициализируется нулевыми битами.[289]

Затем в сноске говорится (курсив добавлен):

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

Хотя нулевой указатель обычно представляется как все 0 бит, такое представление не гарантируется. Чтобы ответить на ваш вопрос напрямую, нет вы не можете полагаться на то, что указатели структуры calloc()d будут NULL.


Если вы хотите установить для всех содержащихся указателей динамически выделяемой структуры значение NULL, вы можете использовать следующее:

struct a *s = malloc(sizeof *s);
*s = (struct a){0};

C11:

6.7.9.21 Если в списке, заключенном в фигурные скобки, меньше инициализаторов, чем элементов или членов агрегата, [...] оставшаяся часть агрегата должна быть инициализирована неявно так же, как объекты, которые имеют статическую продолжительность хранения

а также

6.7.9.10 ... Если объект со статической или потоковой длительностью хранения не инициализируется явно, то:
— если он имеет тип указателя, он инициализируется нулевым указателем;< бр>

C требует, чтобы у вас был хотя бы один элемент внутри фигурных скобок, поэтому я использую {0} вместо {}. Остальные элементы инициализируются в соответствии с указанными выше правилами, что приводит к нулевым указателям. Насколько я могу судить, правила для этого одинаковы в C11 и C99.

person Ryan Haining    schedule 08.08.2014

Стандарт ISO C для calloc требует инициализировать все до 0. Это означает, что если вы в конечном итоге будете рассматривать память, выделенную calloc, как указатели, она действительно изначально будет содержать указатели NULL (0).

person T.E.D.    schedule 02.05.2011
comment
Быть 0 неточным. Вы имеете в виду, если все нулевые биты являются представлением для нулевых указателей. - person R.. GitHub STOP HELPING ICE; 02.05.2011