В моем курсе по компьютерным наукам нас учили методу сохранения значения в 0-м элементе неправильно выделенного массива с последующим приращением массива, чтобы в нем могли храниться такие вещи, как размер массива. элемент и получен позже.
Жаль это слышать, так как это полная чушь. Вместо этого используйте struct
.
Что хуже, чем бессмысленная задача, так это то, что она также вызывает неопределенное поведение (см. C стандарт 6.5.6). Вы не можете делать арифметику указателей c, если они не указывают на массив того же типа, что и сам указатель.
Кроме того, это может привести к неправильному доступу. В зависимости от ЦП неправильное выравнивание может привести к излишне медленным перехватам кода или инструкций, приводящим к программе cra sh. Неправильное обращение также является неопределенным поведением.
Кроме того, сохранение результата различных операций над типом данных, например среднего, внутри самого типа данных не имеет никакого смысла вообще. Они должны быть обновлены, как только значение изменится, что приведет к ненужному раздутию и неэффективному коду.
Немедленно забудьте обо всей этой чепухе. Ваша программа не может быть исправлена или отремонтирована, так как сама идея в корне неверна. Сделайте так вместо этого:
typedef struct
{
int i;
double d;
int array[];
} something;
something* s = malloc(sizeof(something) + sizeof(int[n]));
s->i = ...;
s->d = ...;
for(int i=0; i<n; i++)
s->array[i] = ...;
...
free(s);
В частности, ваш код вызывает неопределенное поведение в соответствии с C17 6.5.6 §7 и §8:
Для целей этих операторов указатель на объект, который не является элементом массива, ведет себя так же, как указатель на первый элемент массива длиной один с типом объекта в качестве его типа элемента.
Когда выражение с целочисленным типом добавляется или вычитается из указателя, результат имеет тип операнда указателя. / - / Если и операнд-указатель, и результат указывают на элементы одного и того же объекта массива ... / - / ... в противном случае поведение не определено.
Существует также проблема псевдонимов указателей, но (к счастью?) в данном случае это не применимо, поскольку данные, размещенные в куче, не имеют «эффективного типа», пока не будут записаны. Пока вы пишете на указанный c адрес с тем же типом указателя, это не неопределенное поведение.
Соответствующие части, касающиеся несоосности, - C17 6.3.2.3/7:
Указатель на тип объекта может быть преобразован в указатель на другой тип объекта. Если результирующий указатель неправильно выровнен для ссылочного типа, поведение не определено.