@ Azoros,
Ваш код работает для целых чисел, поскольку вы определяете тип указателя как целые числа. Когда вы определяете тип указателя как double, процессор попытается обработать каждый элемент как тип данных double. Внутренне целые и двойные числа хранятся в разных форматах. Вот почему, когда вы пытаетесь извлечь целочисленное значение из двойного типа данных, оно не работает.
Итак, если я правильно понимаю вашу проблему, вы хотите, чтобы массив с нулевым элементом определялся как целое число, которое содержит длину массива. Остальные элементы должны содержать значения данных, которые могут быть другого типа, чем первый элемент.
Я бы подошел к этой проблеме, определив указатель массива как байтовый массив (void *). Затем при доступе к элементам я просто скажу процессору, с каким типом данных он имеет дело.
Вот как это делается на практике:
Измените определение указателя на указатель байта.
void* array;
Выделите массив по размеру, который включает как элемент длины массива, так и элементы данных.
array = calloc(1, INT_SIZ + (noe * soe));
Переместите значение размера в первую позицию массива. Обратите внимание, что на машине Windows x86 это скопирует 4 байта данных.
memcpy(array, (void*)&noe, INT_SIZ);
Возвращает смещение адреса памяти на размер первого элемента. На компьютере x86 это будет смещено на 4 байта
return (void*)(((int*)(array)) + 1);
Здесь полный код, который использует модифицированную процедуру createArray.
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# define INT_SIZ sizeof(int)
# define GetSize( pt ) ((int *)pt)[-1]
# define GetElement( pt, etype, idx ) ((etype *)pt)[idx]
# define InsertElement( pt, etype, idx, val ) \
{ \
etype temp = val; \
memcpy ( (void *) &((etype *)pt)[idx], &temp, sizeof(etype) ); \
}
void * createArray(int noe, /* Number of elements */
int soe) /* Size of element */
{
void *array;
/* Allocate the array */
array = calloc(1, INT_SIZ + (noe * soe));
if ( array == NULL ) return NULL;
/* Copy the integer value representing the number of elements to the first
element in the array */
memcpy ( array, (void *) &noe, INT_SIZ );
/* Return the pointer value offset by the size of an int */
return (void *) (((int *)(array))+1);
}
int main(void)
{
void *array;
int i=0;
array = createArray(10, sizeof(int));
InsertElement ( array, int, 0, 65534 );
printf("%d\n", *(int *)( ((int *)(array)) - 1) ); /* pointer syntax */
printf("%d\n", ((int *)array)[-1] ); /* array syntax */
printf("%d\n", GetSize(array) );
printf ( "Element #%d: %d\n", 0, GetElement ( array, int, 0 ) );
puts ( "\nDemonstrating Array of Doubles --------------------------------");
array = createArray(10, sizeof(double));
InsertElement ( array, double, 0, 3.0 );
InsertElement ( array, double, 1, 3.1 );
InsertElement ( array, double, 2, 3.2 );
printf("Array size: %d\n", GetSize(array) );
for ( i=0; i<3; i++ )
printf ( "Element #%d: %lf\n", i, GetElement ( array, double, i ) );
free ( ((int *)(array))-1 );
}
Вот вывод:
10
10
10
Element #0: 65534
Demonstrating Array of Doubles --------------------------------
Array size: 10
Element #0: 3.000000
Element #1: 3.100000
Element #2: 3.200000
Замечания по поводу кода
- Массив обрабатывается как массив с нулевым основанием, как и любой другой массив C.
- Хотя в процедуре, Я добавил проверку, чтобы увидеть, была ли выделена память, аналогичные проверки должны выполняться любыми вызывающими подпрограммами createArray.
- Были добавлены определения макросов, чтобы сделать код более читабельным.