Всегда ли calloc() двойного поля оценивается как 0,0?

  • Всегда ли calloc() двойного поля оценивается как 0.0?

Кроме того:

  • Всегда ли calloc() поля float оценивается как 0.0f?
  • Всегда ли calloc() поля int или unsigned int оценивается как 0?

То есть всегда ли assert() ниже работает на всех платформах?

double* d = calloc(1, sizeof(double));
assert(*d == 0.0);
free(d);

person st12    schedule 14.12.2018    source источник


Ответы (4)


calloc обнуляет все байты выделенной памяти.

Как оказалось, это также допустимый формат IEEE754 (который является наиболее распространенным форматом для значений с плавающей запятой на компьютеры) представление для 0.0.

IIRC нет части спецификации C, которая требует реализации для использования IEEE754, поэтому, если быть придирчивой, она не переносима. В действительности, однако, это так (и если вы когда-либо собираетесь работать с системой, отличной от IEEE754, то вы должны накопить достаточно опыта, чтобы уже знать это и как решать такие проблемы).

Также обратите внимание, что это также справедливо для указателей. Во всех системах, с которыми вы, вероятно, столкнетесь, нулевой указатель должен быть равен 0. Но могут быть системы, где его нет, но если вы работаете с такими системами, вы уже должны знать об этом (и если вы используете NULL, то это не должно быть проблемой).

person Some programmer dude    schedule 14.12.2018
comment
Спасибо за ссылку на IEEE 754. - person st12; 14.12.2018
comment
Я не уверен в вашем объяснении нулевого указателя. В конце концов, язык C гарантирует, что нулевой указатель будет равен 0, даже в тех необычных системах, где calloc не гарантирует инициализацию объекта размером с указатель значением нулевого указателя. Я не уверен, что вы имеете в виду (и если вы используете NULL, это не должно быть проблемой). - person Ian Abbott; 14.12.2018
comment
@IanAbbott Возможно, целочисленный литерал 0 был распознан как нулевой указатель (как в C++, но тогда это должен быть фактический литерал 0, а не целочисленная переменная со всеми нулевыми битами) в более поздних версиях стандарта C, но переносимый нулевой указатель есть, есть и всегда будет макросом NULL. - person Some programmer dude; 14.12.2018
comment
@Someprogrammerdude Это не обязательно должен быть буквальный 0. Это просто должно быть целочисленное константное выражение со значением 0 или такое выражение, приведенное к void *. Вы правы в том, что значение 0, хранящееся в lvalue целочисленного типа, нельзя сравнивать со значением указателя. - person Ian Abbott; 17.12.2018

В документации C11 есть это явное уведомление для calloc

Сноски

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

На практике все нулевые биты являются (или) представлением для 0.0 и нулевого указателя на основных платформах и истинны для IEEE 754.

person Antti Haapala    schedule 14.12.2018

стандарт C намеренно избегает указания способа, которым float и double представлены:

6.2.6.1 Общие положения

  1. Представления всех типов не определены, за исключением случаев, указанных в этом подпункте.

Поэтому у вас нет гарантии, что calloc выдаст значения 0,0.

С другой стороны, представление целых чисел без знака определяется следующим образом:

Если имеется N битов значения, каждый бит должен представлять разную степень 2 от 1 до 2N−1, чтобы объекты этого типа могли представлять значения от 0 до 2 N − 1 с использованием чистого двоичного представления.

Следовательно, значение calloc-ed unsugned int гарантированно равно нулю.

person Sergey Kalinichenko    schedule 14.12.2018
comment
Увлекательно о unsigned int. - person st12; 14.12.2018

Все нулевые байты для float не означают 0.0. Из здесь

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

person Gaurav Sehgal    schedule 14.12.2018
comment
Я должен был прочитать cppreference.com для calloc(), прежде чем задавать вопрос. Я смотрел только на cplusplus.com. :-) - person st12; 14.12.2018