How to create an array of initialized pointers - c

I have a structure:
struct Path{
int8_t maxtopy;
};
And I want to create an array of pointers to structure Path. I've tried something like that:
int main(){
struct Path *paths[NUMBER_OF_PATHS];
init_paths(paths);
}
void init_paths(struct Path **paths){
paths[0]->maxtopy = -1;
for(int i = 1; i < NUMBER_OF_PATHS; i++)
paths[i]->maxtopy = -1;
}
It is not going to work. Value to the first path is assigned correctly. But when for loop starts I am gettting Segmentation fault. I already figured out that when I am creating array of pointers, only the first pointer is going to be assigned to some structure. So I cannot e.g. paths[1]->maxtopy = -1;, because paths[1] doesn't point to any existing structure.
I have tried something like this:
for(int i = 1; i < NUMBER_OF_PATHS; i++){
static struct Path a;
paths[i] = &a;
paths[i]->maxtopy = i;
}
It doesn't work because it initialize a only once. So every pointer in paths array points to the same structure.
My question is: How to create an array of pointers that point to initialized structures?

You've created an array of pointers, butt the pointers need to point to something. You can dynamically allocate each with malloc.
struct Path{
int8_t maxtopy;
};
int main(void) {
struct Path *paths[NUMBER_OF_PATHS];
for (size_t i = 0; i < NUMBER_OF_PATHS; i++) {
paths[i] = malloc(sizeof(struct Path));
paths[i]->maxtopy = i;
}
return 0;
}
Of course, if your array is declared in main and is not of excessive size, you may want to simply write the following.
int main(void) {
struct Path paths[NUMBER_OF_PATHS];
for (size_t i = 0; i < NUMBER_OF_PATHS; i++) {
paths[i].maxtopy = i;
}
return 0;
}

const int NUMBER_OF_PATHS = 10;
struct Path {
int8_t maxtopy;
};
void init_paths(struct Path** paths) {
for (int i = 0; i < NUMBER_OF_PATHS; i++) {
paths[i] = (Path*)malloc(sizeof(Path));
paths[i]->maxtopy = i;
}
}
int main() {
struct Path* paths[NUMBER_OF_PATHS];
init_paths(paths);
for (auto i : paths) {
printf("%d\n", i->maxtopy);
}
}

Related

LinkList not adding a new Node [duplicate]

I'm trying to create a function that creates a variable sized 2D funct array. I'm using the following code, which seems to work just fine on its own:
typedef struct
{
//Starter Properties
int TypeB;
int TypeF;
int TypeW;
//Randomized Properties
int RandB;
int RandF;
int RandW;
//Derived Properties
int Speed;
} MapTileData;
MapTileData **Map;
int i, x=5, y=5;
//Allocate Initial Space
Map = (MapTileData**)calloc(x, sizeof(MapTileData));
for(i = 0; i < x; i++)
{
Map[i] = (MapTileData*)calloc(y, sizeof(MapTileData));
}
So the above code creates a 2D struct array. My attempts to move the code to a function have been less successful, giving segmentation faults when trying to print the array:
void CreateMap(MapTileData **Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
Map = (MapTileData**)calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = (MapTileData*)calloc(ySize, sizeof(MapTileData));
}
}
Used in the code:
MapTileData **MapTile;
CreateMap(MapTile,5,5);
Any and all help is greatly appreciated!
Function arguments are passed by value in C and modifying arguments in callee won't affect caller's local variables.
Use pointers to modify caller's local variables.
void CreateMap(MapTileData ***Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
*Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
(*Map)[i] = calloc(ySize, sizeof(MapTileData));
}
}
Usage in the code:
MapTileData **MapTile;
CreateMap(&MapTile,5,5);
Alternate way: Pass the allocated array via the return value.
MapTileData **CreateMap(int xSize, int ySize)
{
//Variables
MapTileData **Map;
int i;
//Allocate Initial Space
Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = calloc(ySize, sizeof(MapTileData));
}
//Return the value
return Map;
}
Usage in the code:
MapTileData **MapTile;
Maptile = CreateMap(5,5);
Also note that they say you shouldn't cast the result of malloc() and its family in C.

allocating memory to pointer of typedef

I'm hiding a pointer with the typedef and I'm trying to make an array of it. my structure is:
typedef struct s {
int y;
int x;
int value;
} s;
typedef s *t;
and the main:
int main()
{
t *var;
int arg;
var = malloc(sizeof(t*));
arg = 40;
for (int x = 0; x < arg; x++)
{
var[x] = malloc(sizeof(t));
var[x]->x = -1;
var[x]->y = -1;
var[x]->value = 0;
}
for (int x = 0; x < arg; x++)
{
printf("|%d| ",var[x]->value);
}
return 0;
}
sometime it just goes to segmentation fault and sometimes the value is just dirty, but it still means that it did not allocated the memory as intented. what am I missing? I'm just trying to make an array of type t with arg length which must be a variable
I'm hiding a pointer with the typedef
This very bad practice is the root of all your bugs. Simply don't hide pointers behind typedef.
Because now you have a t* var which is actually a s**. Then you call var = malloc(sizeof(t*)); which is completely wrong, because you allocate room for a s**.
You should have allocated room for 40 * sizeof(s*) or otherwise var[x] will seg fault.
And then typedef or not, this is not a 2D array but a segmented look-up table, which adds extra complexity and slower code, for absolutely nothing gained. See Correctly allocating multi-dimensional arrays. But it doesn't even look like you need a 2D array, so what's all of that coming from?
With all of this in mind, lets go with the KISS principle and rewrite the code from scratch:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int y;
int x;
int value;
} s;
int main (void)
{
int arg = 40;
s* var = malloc(arg * sizeof(*var));
for (int i = 0; i < arg; i++)
{
var[i].x = -1;
var[i].y = -1;
var[i].value = 0;
}
for (int i = 0; i < arg; i++)
{
printf("|%d| ",var[i].value);
}
free(var);
return 0;
}
A 2D version would use s (*var)[y] = malloc( sizeof(s[x][y]) ); instead.

inicializing a structure with arrays of arrays [duplicate]

I'm trying to create a function that creates a variable sized 2D funct array. I'm using the following code, which seems to work just fine on its own:
typedef struct
{
//Starter Properties
int TypeB;
int TypeF;
int TypeW;
//Randomized Properties
int RandB;
int RandF;
int RandW;
//Derived Properties
int Speed;
} MapTileData;
MapTileData **Map;
int i, x=5, y=5;
//Allocate Initial Space
Map = (MapTileData**)calloc(x, sizeof(MapTileData));
for(i = 0; i < x; i++)
{
Map[i] = (MapTileData*)calloc(y, sizeof(MapTileData));
}
So the above code creates a 2D struct array. My attempts to move the code to a function have been less successful, giving segmentation faults when trying to print the array:
void CreateMap(MapTileData **Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
Map = (MapTileData**)calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = (MapTileData*)calloc(ySize, sizeof(MapTileData));
}
}
Used in the code:
MapTileData **MapTile;
CreateMap(MapTile,5,5);
Any and all help is greatly appreciated!
Function arguments are passed by value in C and modifying arguments in callee won't affect caller's local variables.
Use pointers to modify caller's local variables.
void CreateMap(MapTileData ***Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
*Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
(*Map)[i] = calloc(ySize, sizeof(MapTileData));
}
}
Usage in the code:
MapTileData **MapTile;
CreateMap(&MapTile,5,5);
Alternate way: Pass the allocated array via the return value.
MapTileData **CreateMap(int xSize, int ySize)
{
//Variables
MapTileData **Map;
int i;
//Allocate Initial Space
Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = calloc(ySize, sizeof(MapTileData));
}
//Return the value
return Map;
}
Usage in the code:
MapTileData **MapTile;
Maptile = CreateMap(5,5);
Also note that they say you shouldn't cast the result of malloc() and its family in C.

Getting the value of a pointer to a structure to another pointer to a structure

..then to an array, or along those lines. I'm so confused on what I'm supposed to do.
Here are the structs:
typedef struct {
char name[30];
} PersonType;
typedef struct {
PersonType *personInfo;
} StudentType;
typedef struct {
StudentType students[30];
} GraduateType;
I want to get the name of the PersonType. Something like this, in main():
GraduateType *gptr = (GraduateType *) calloc(3, sizeof(GraduateType));
// Assume here that info has been scanf()'d
int i, j;
for(i = 0; i < 3; i++) {
for(j = 0; j < 2; j++) {
if(strcmp(gptr[i].students[j].personInfo.name, "asd")) { // <- This
// blah
}
}
}
How?
You were almost there. personInfo is a pointer, so you should treat it as such:
gptr[i].students[j].personInfo->name

C and dynamic structure element access

I have this complicated structure thingie:
#include <stdlib.h>
typedef struct {
int x;
int y;
} SUB;
typedef struct {
int a;
SUB *z;
} STRUCT;
#define NUM 5
int main(void)
{
STRUCT *example;
int i;
example = malloc(sizeof(STRUCT));
example->z = malloc(NUM * sizeof(SUB));
for(i = 0; i < NUM; ++i) {
/* how do I access variable in certain struct of array of z's */
}
return 0;
}
example is dynamically allocated structure and z inside the example is dynamically allocated array of SUB structures.
How do I access certain variable in certain element of structure z?
I have been trying something like this: example->z[i].x but it doesnt seem to work.
At the moment I am using this shabby looking workaraound:
SUB *ptr = example->z;
int i;
for(i = 0; i < amount_of_z_structs; ++i) {
/* do something with 'ptr->x' and 'ptr->y' */
ptr += sizeof(SUB);
}
Your problem isn't where you say it is. Your code as posted gives a compile error:
error: request for member ā€˜zā€™ in something not a structure or union
at the line
example.z = malloc(sizeof(STRUCT));
because you meant to write example->z, since example is a pointer to STRUCT, not a STRUCT.
From there on, you can access example->z[i].x exactly as you said. That syntax has always been fine.
For example:
/* your declarations here */
example = malloc(sizeof(STRUCT));
example->z = malloc(NUM * sizeof(SUB));
for(i = 0; i < NUM; ++i) {
example->z[i].x = i;
example->z[i].y = -i;
printf("%d %d\n", example->z[i].x, example->z[i].y);
}
/* output:
0 0
1 -1
2 -2
3 -3
4 -4
*/
When you have pointers pointing to pointers you often end up running into precedence issues. I can't recall if this is one, but you might try (example->b)[i].x.
First of all, your second malloc is wrong; example is a pointer so this:
example.z = malloc(NUM * sizeof(SUB));
should be this:
example->z = malloc(NUM * sizeof(SUB));
Then in your loop you can say things like this:
example->z[i].x = i;
example->z[i].y = i;
You'll also want to have this near the top of your file:
#include <stdlib.h>
Try this:
int my_x = example[3].z[2].x;
The above code will first access the example[3] (the fourth element of the example array).
Once you get that particular element, its contents can be automatically access in the same way as you do with normal objects.
You then access z[2] from that element. Note that, example[3] is an element, so you could use a . to access its members; if its an array, you can access it as an array.
So till now, example[3].z[2] is one element of the SUB array inside one element of the example array.
Now you can simply access the member x using the way shown above.
typedef struct {
int x;
int y;
} SUB;
typedef struct {
int a;
SUB *z;
} STRUCT;
STRUCT *example;
int main() {
example = malloc(sizeof(STRUCT)*10); //array of 10;
int i=0,j=0;
for (;i<10;i++){
example[i].a = i;
example[i].z = malloc(sizeof(SUB)*5);
for (j=0; j<5; j++)
example[i].z[j].x = example[i].z[j].y = j;
}
//access example[3] and access z[2] inside it. And finally access 'x'
int my_x = example[3].z[2].x;
printf("%d",my_x);
for (i=0;i<10;i++){
printf("%d |\n",example[i].a);
//example[i].z = malloc(sizeof(SUB)*5);
for (j=0; j<5; j++)
printf("%d %d\n",example[i].z[j].x,example[i].z[j].y);
free(example[i].z);
}
free(example);
}
In the 'shabby workaround', you wrote:
SUB *ptr = example->z;
int i;
for(i = 0; i < amount_of_z_structs; ++i) {
/* do something with 'ptr->x' and 'ptr->y' */
ptr += sizeof(SUB);
}
The problem here is that C scales pointers by the size of the object pointed to, so when you add 1 to a SUB pointer, the value is advanced by sizeof(SUB). So, you simply need:
SUB *ptr = example->z;
int i;
for (i = 0; i < NUM; ++i) {
ptr->x = ptr->y = 0;
ptr++;
}
Of course, as others have said, you can also do (assuming C99):
for (int i = 0; i < NUM; ++i)
example->z[i].x = example->z[i].y = 0;
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define NUM 5
typedef struct
{
int x;
int y;
}SUB;
typedef struct
{
int a;
SUB* z;
}STRUCT;
void main(void)
{
clrscr();
printf("Sample problem..\n\n");
STRUCT* example;
int i;
example = (STRUCT*)malloc(sizeof(STRUCT));
example->z = (SUB*)malloc(NUM * sizeof(SUB));
for(i = 0; i < NUM; i++)
{
example->z[i].x = i +1;
example->z[i].y = (example->z[i].x)+1;
printf("i = %d: x:%d y:%d\n", i, example->z[i].x, example->z[i].y);
}
}

Resources