Вы достаточно близки к тому, что вы хотите, согласно вашему комментарию .
Использование массива структур
Вот адаптация вашего кода. Основным изменением является использование ArrayOfStructs *array
вместо использования указателя на указатель. Кроме того, поскольку вы решили использовать uint_fast64_t
для типа данных, вы должны использовать PRIuFAST64
из <inttypes.h>
, чтобы получить правильную строку формата. Было бы лучше изменить это на size_t
; вы не заметите разницу в производительности на какой-либо разумной системе (но код использует формат PRIuFAST64
).
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <inttypes.h>
typedef struct
{
double X;
double Y;
} ArrayOfStructures;
typedef struct
{
uint_fast64_t length;
ArrayOfStructures *array;
} Points;
typedef struct
{
Points *points;
} Config;
static
void add_new_array(Config *conf)
{
printf("conf=%p\n", conf);
printf("conf->points=%p\n", conf->points);
printf("conf->points->length=%" PRIuFAST64 "\n", conf->points->length);
printf("conf->points->array=%p\n", conf->points->array);
ArrayOfStructures *temp = calloc(conf->points->length, sizeof(ArrayOfStructures));
printf("temp=%p\n", temp);
conf->points->array = temp;
printf("conf->points->array=%p\n", conf->points->array);
}
static
void another_function(Config *conf)
{
conf->points->length = 1;
add_new_array(conf);
conf->points->array[0].X = 0.1;
conf->points->array[0].Y = 0.2;
printf("The result: X=%.12f, Y=%.12f, length=%" PRIuFAST64 "\n",
conf->points->array[0].X, conf->points->array[0].Y, conf->points->length);
}
static
void some_function(Config *conf)
{
// To pass the structure to another function
another_function(conf);
}
int main(void)
{
// Stack's allocated memory
Config conf_;
Config *conf = &conf_;
memset(conf, 0x0, sizeof(Config));
// Stack's allocated memory
Points points;
memset(&points, 0x0, sizeof(Points));
conf->points = &points;
some_function(conf);
return(EXIT_SUCCESS);
}
При запуске это выдает:
conf=0x7ffeed6883f8
conf->points=0x7ffeed688400
conf->points->length=1
conf->points->array=0x0
temp=0x7fef13c02a80
conf->points->array=0x7fef13c02a80
The result: X=0.100000000000, Y=0.200000000000, length=1
Он не падает. Я не запускал его под Valgrind . Он сообщит об утечках для выделенной памяти.
Ваше имя типа ArrayOfStructures
для типа, в котором нет массива, кажется крайне неуместным. Я ожидал, что ему дадут имя, например Point
. Я предполагаю, что ваша структура Config
была минимизирована для этого вопроса (если так, спасибо). Если нет, то структура, содержащая один указатель на другую структуру, не дает никакой выгоды. Это просто замедляет ваш доступ к данным - значительно перевешивает любую выгоду от использования uint_fast64_t
вместо size_t
. Вы должны быть осторожны с распределением памяти для структуры Config
; Вы не можете просто освободить все внутри Config
и его дочерних структур в данный момент.
Использование массива указателей на структуры
Это очень похоже на последний код, но вам нужен дополнительный набор памяти. Я сделал это в цикле, так как единственная причина использования этого дизайна - позволить вам выделять указанные структуры отдельно. Иначе это просто излишне сложно. Я сделал несколько небольших уборок; возможны и другие улучшения. Я добавил функцию дампа структуры dump_points()
, которую я могу использовать для печати значений в разных точках.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <inttypes.h>
typedef struct
{
double X;
double Y;
} ArrayOfStructures;
typedef struct
{
size_t length;
ArrayOfStructures **array;
} Points;
typedef struct
{
Points *points;
} Config;
static void dump_points(const char *tag, const Points *points)
{
printf("%s (%zu, %p)\n", tag, points->length, (void *)points);
for (size_t i = 0; i < points->length; i++)
printf("%zu: (%.12f, %.12f) %p\n", i, points->array[i]->X, points->array[i]->Y,
(void *)points->array[i]);
}
static
void add_new_array(Config *conf)
{
printf("conf=%p\n", (void *)conf);
printf("conf->points=%p\n", (void *)conf->points);
printf("conf->points->length=%zu\n", conf->points->length);
printf("conf->points->array=%p\n", (void *)conf->points->array);
conf->points->array = calloc(conf->points->length, sizeof(conf->points->array[0]));
for (size_t i = 0; i < conf->points->length; i++)
conf->points->array[i] = calloc(1, sizeof(conf->points->array[i][0]));
printf("conf->points->array=%p\n", (void *)conf->points->array);
printf("conf->points->array[0]=%p\n", (void *)conf->points->array[0]);
dump_points("Inside add new array", conf->points);
}
static
void another_function(Config *conf)
{
conf->points->length = 3;
add_new_array(conf);
conf->points->array[0]->X = 0.1;
conf->points->array[0]->Y = 0.2;
conf->points->array[1]->X = 1.1;
conf->points->array[1]->Y = 1.2;
conf->points->array[2]->X = 2.1;
conf->points->array[2]->Y = 2.2;
dump_points("Inside another function", conf->points);
}
static
void some_function(Config *conf)
{
// To pass the structure to another function
another_function(conf);
dump_points("Inside some function", conf->points);
}
int main(void)
{
// Stack's allocated memory
Config conf_;
Config *conf = &conf_;
memset(conf, 0x0, sizeof(Config));
// Stack's allocated memory
Points points;
memset(&points, 0x0, sizeof(Points));
conf->points = &points;
some_function(conf);
dump_points("Inside main", conf->points);
return(EXIT_SUCCESS);
}
Пример вывода (macOS 10.14.5 Mojave; GCC 9.1.0):
conf=0x7ffee6f6b408
conf->points=0x7ffee6f6b410
conf->points->length=3
conf->points->array=0x0
conf->points->array=0x7f9c0a402a70
conf->points->array[0]=0x7f9c0a402a90
Inside add new array (3, 0x7ffee6f6b410)
0: (0.000000000000, 0.000000000000) 0x7f9c0a402a90
1: (0.000000000000, 0.000000000000) 0x7f9c0a402aa0
2: (0.000000000000, 0.000000000000) 0x7f9c0a402ab0
Inside another function (3, 0x7ffee6f6b410)
0: (0.100000000000, 0.200000000000) 0x7f9c0a402a90
1: (1.100000000000, 1.200000000000) 0x7f9c0a402aa0
2: (2.100000000000, 2.200000000000) 0x7f9c0a402ab0
Inside some function (3, 0x7ffee6f6b410)
0: (0.100000000000, 0.200000000000) 0x7f9c0a402a90
1: (1.100000000000, 1.200000000000) 0x7f9c0a402aa0
2: (2.100000000000, 2.200000000000) 0x7f9c0a402ab0
Inside main (3, 0x7ffee6f6b410)
0: (0.100000000000, 0.200000000000) 0x7f9c0a402a90
1: (1.100000000000, 1.200000000000) 0x7f9c0a402aa0
2: (2.100000000000, 2.200000000000) 0x7f9c0a402ab0
Обнадеживает то, что данные не повреждены, поскольку они передаются обратно в цепочку функций.