When I use this code I would like to turn to every element of array of structures like this:
array[0]->X;
array[1]->X;
I tried everything I could, but in all cases I've had Segmentation fault. What am I doing wrong?
Please look at blocks between #if 0 #endif
#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;
void add_new_array(Config *conf)
{
printf("conf=%p\n",conf);
printf("conf->points=%p\n",conf->points);
printf("conf->points->length=%zu\n",conf->points->length);
printf("conf->points->array=%p\n",conf->points->array);
#if 0
ArrayOfStructures *temp = (ArrayOfStructures*)calloc(conf->points->length,sizeof(ArrayOfStructures));
printf("temp=%p\n",temp);
// Segmentation fault
*conf->points->array = temp;
#else
conf->points->array = (ArrayOfStructures **)calloc(conf->points->length,sizeof(ArrayOfStructures *));
#endif
printf("conf->points->array=%p\n",conf->points->array);
}
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=%zu\n",conf->points->array[0]->X,conf->points->array[0]->Y,conf->points->length);
}
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);
}
Compiled using:
gcc -D_SVID_SOURCE -g -ggdb -ggdb1 -ggdb2 -ggdb3 -O0 -DDEBUG -std=c11 -Wall --pedantic arryay.c -o array
I tried to find answers for handling a double pointer, but everything is very confusing.
You don't seem to initialize length
to a meaningful value. Therefore you don't actually allocate memory, since you call calloc()
with the first argument being zero.
(Disclaimer: I haven't tested the code, but that seems to be wrong.)
You're fairly close to what you want according to your comment .
Here's an adaptation of your code. The primary change is use ArrayOfStructs *array
instead of using a pointer-to-pointer. Also, because you've decided to use uint_fast64_t
for a data type, you have to use PRIuFAST64
from <inttypes.h>
to get the correct format string. It would be better to change that to size_t
; you aren't going to spot the performance difference on any reasonable system (but the code uses the format 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);
}
When run, this produces:
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
It doesn't crash. I've not run it under Valgrind . It will report leaks for the allocated memory.
Your type name ArrayOfStructures
for a type that has no array in it seems wildly inappropriate. I'd've expected that to be given a name such as Point
. I assume your Config
structure has been minimized for this question (if so, thank you). If not, then the structure holding a single pointer to another structure is not giving you any benefit. It is just slowing down your access to the data — vastly outweighing any benefit from using uint_fast64_t
instead of size_t
. You'll need to be careful about your allocation of memory for the Config
structure; you can't simply free everything inside the Config
and its child structures at the moment.
This is very similar to the last code, but you need an extra set of memory allocations. I've made that into a loop since the only reason for using this design is to allow you to allocate the pointed at structures separately. Otherwise, it is just needlessly complex. I've made a few minor cleanups; there are more improvements possible. I've added a structure dumper function, dump_points()
, which I can and do use to print values at different 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);
}
Sample output (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
It's reassuring to see that the data is not corrupted as it is passed back up the chain of functions.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.