I'm having issues filling a 2d array of a struct inside a struct. It allows me to do it for pixels[0][1], pixels[0][2]....etc. However, once I increase the first index i.e pixels[1][1], I get a bus error 10. Any help would be appreciated. I've cut out some code to make it more readable but if you require all of it let me know! What the program is doing is reading a PPM image and displaying the information, the trouble i'm having is storing the pixels of the image.
#define MAX_HEIGHT 4
#define MAX_WIDTH 4
typedef struct Pixel{
int red;
int green;
int blue;
}Pixel;
typedef struct PPM{
char code[2];
int width, height;
int max;
Pixel * pixels[MAX_HEIGHT][MAX_WIDTH];
}PPM;
struct PPM * getPPM(FILE * fd){
PPM * image = NULL;
image = malloc(sizeof(PPM));
//have got all the other PPM info here ask if needed
int i;
int j;
for(i = 0; i<MAX_HEIGHT-1; i++){
for(j = 0; j<MAX_WIDTH-1; j++){
// struct Pixel newPPM_Pixel;
if(fscanf(fd, "%d %d %d", &image->pixels[i][j]->red, &image->pixels[i][j]->green, &image->pixels[i][j]->blue) == 3){
//rgb_array[i][j] = newPPM_Pixel;
printf("/ %d / %d / %d", image->pixels[i][j]->red, image->pixels[i][j]->green, image->pixels[i][j]->blue);
}
}
}
return image;
}
Change line :
Pixel * pixels[MAX_HEIGHT][MAX_WIDTH];
to :
Pixel pixels[MAX_HEIGHT][MAX_WIDTH]; //without an asterisk
This is the way to declare a 2D array. If you want pixels to be a pointer, declare it like this :
Pixel **pixels;
and then dynamically allocate memory for it :
int i;
pixels = malloc (MAX_HEIGHT*sizeof(Pixel*));
if (pixels == NULL)
printf ("Error allocating memory\n");
for (i = 0; i < MAX_HEIGHT; i++)
pixels[i] = malloc(MAX_WIDTH*sizeof(Pixel));
if (pixels[i] == NULL)
printf ("Error allocating memory\n");
You can read more about 2D dynamic memory allocation here.
Related
I'm trying to allocate the char** path array in my batiment struct
#ifndef SDL2_BATIMENTS_H
#define SDL2_BATIMENTS_H
typedef struct{
int x;
int y;
}vecteur;
typedef struct{
int numtype; //Détermine quelle representation du batiment (route nor/ route sud...)
char** tabpath; // tableau de chemin d'acces aux images
vecteur size; // Taille du batiment en (x,y)
int habitant;
}batiment;
typedef struct {
vecteur** tuile;
batiment* tabbatiment; //tableau de batiment
}Monde;
Monde* InitBatiment(Monde* monde);
vecteur toGrid(float x,float y);
#endif //SDL2_BATIMENTS_H
I've tried to allocate it like an array[][], at first it seems to be working with no error but everytime i try to access it my program crashes
for(int i=0; i<14;i++)
{
monde->tabbatiment[i].tabpath = malloc(7 * sizeof (char*));
for (int y = 0; y < 7; y++)
monde->tabbatiment[i].tabpath[i] = (char*)malloc(50 * sizeof(char));
}
Ok First of all thank you for your answer, I changed my code to this but everytime my program try to call strcpy it crashes.
I think I still have an allocation problem or a memory leak.
for(int i=0; i<14;i++)
{
monde->tabbatiment[i].tabpath = calloc(10,sizeof(char*));
for(int y = 0; y < 10; y++)
monde->tabbatiment[i].tabpath[i] = calloc(30 ,sizeof(char));
}
FILE *f;
char c;
int numbatiment;
f=fopen("batiment.txt","r");
int x,y,numbat,numtype;
const char path[50];
for(int i =0;i<16;i++)
{
fscanf(f,"%d %d %d %d %s ",&numbat,&x,&y,&numtype,&path);
printf("%s",path);
strcpy(monde->tabbatiment[numbat].tabpath[numtype],path);
monde->tabbatiment[numbat].size.x = x ;
monde->tabbatiment[numbat].size.y=y ;
monde->tabbatiment[numbat].numtype = numtype;
printf("%d %d %d %d %s\n",numbat,monde->tabbatiment[numbat].size.x,monde->tabbatiment[numbat].size.y,monde->tabbatiment[numbat].numtype,monde->tabbatiment[numbat].tabpath[numtype]);
}
fclose(f);
Could you elaborate what you are exactly trying to accomplish with the code? It feels like there is more to it then a simple bug, but more of an implementation issue as a whole.
I cannot replicate your SEGFAULT for what it's worth. I do run into a lot of memory issues in valgrind, all of which could be attributed that you allocate memory in a loop, where you could've easily done it in a linear block (hence why I'm afraid that there might be more to this).
To directly answer your question: allocating memory for a string can go 2 ways: either you allocate enough memory from the start for which you are certain the any string you throw at it will be smaller than the allocated memory. Or you allocate memory on the go based on the length of the string that you are adding to your array.
In both cases you would be looking at a combination of malloc/calloc and strcpy/strncpy (the latter in both having my preference most often). Allocate memory where the string should reside, than copy a local buffered value to the designated memory address.
Anyway, I've refactored your example to this. I have to say: take a GOOD look at how you are using indexes in loops. You are going out of bounds often, which might trigger a SEGFAULT. For monde->tuile for instance you allocate 35 slots, but the next thing you do is loop the tuile index to 44. I've also included some define statements which are good practice over magic numbers.
#define SIZE_BATIMENT 15
#define SIZE_TUILE 34
#define SIZE_TABPATH 8
#define MAX_STRING_LEN 64
Monde *monde = calloc(1, sizeof monde);
monde->tuile = calloc(SIZE_TUILE, sizeof(vecteur *));
for (int i=0 ; i <= SIZE_TUILE ; i++)
{
monde->tuile[i] = (vecteur*)malloc(45 * sizeof(vecteur));
}
// Assign memory to allow MAX_STRING_LEN sizes
monde->tabbatiment = calloc(SIZE_BATIMENT, sizeof(batiment));
for(int i = 0; i <= SIZE_BATIMENT; i++)
{
monde->tabbatiment[i].tabpath = calloc(SIZE_TABPATH, sizeof(char *));
for (int j = 0; j <= SIZE_TABPATH; j++)
{
monde->tabbatiment[i].tabpath[j] = calloc(MAX_STRING_LEN, sizeof(char));
}
}
This is an excerpt from a Conway's Game of Life-program that I'm writing. In this part I'm trying to get the program to read a file that specifies what cells are to be populated at the start of the game (i.e. the seed).
I get a weird bug. In the read_line function, the program crashes online[i++] = ch statement. When I debug the program, I see that the line-pointer is NULL when it crashes. Fair enough, I think, I should initialize line. But here is the (for me) strange part:
The read_line function has already successfully execute twice and got me the first two lines (4\n and 3 6\n) from the seed file. And when I look at the execution in the debugger, I see that line is indeed holding a value in those first two executions of read_line. How is this possible? How can line be initialized without me initializing it and then suddenly not be initialized anymore?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define MAX_COORDINATE_SIZE 50
#define MAX_FILENAME_SIZE 20
#define MAX_GENERATIONS 10
#define MAX_REPETITION_PERIOD 4
struct coord{ //Holds coordinates to a cell
int x;
int y;
};
struct cell{
int pop; //Populated
int age;
};
struct coord *read_init(FILE *fp, int *i);
static int read_line(FILE *fp, char *line, int max_length);
struct coord read_coords(char *line);
struct cell **create_board(int x, int y);
struct cell **start_game(FILE *fp, int nrows, int ncols);
struct cell new_cell(int x, int y, int pop, int age);
void print_board(struct cell **board, int nrows, int ncols);
void populate_board(struct coord *coords, struct cell ***board, int *n);
int main(int argc, const char * argv[]) {
int gens;
char gens_string[MAX_GENERATIONS];
if(argc != 3){
fprintf(stderr, "Usage: %s <seed-file> <generations>\n<seed-file> can me up to %d characters long\n", argv[0], MAX_FILENAME_SIZE);
exit(1);
}
FILE *fp = fopen(argv[1], "r");
strncat(gens_string, argv[2], MAX_GENERATIONS);
gens = atoi(gens_string);
int nrows = 10;
int ncols = 10;
struct cell **board= start_game(fp, nrows, ncols);
print_board(board, nrows, ncols);
return 0;
}
struct coord *read_init(FILE *fp, int *n){ //Takes in filename and returns list of coordinates to be populated
char raw_n[100];
struct coord *coords;
char *line;
read_line(fp, raw_n, 100); // get the first line of the file (number of popuated cells)
*n = atoi(raw_n);//make an int out of raw_n
coords = malloc(sizeof(struct coord)*(*n)); //Allocate memory for each coord
for(int i = 0; i<(*n); i++){ // for each line in the file (each populated cell)
read_line(fp, line, MAX_COORDINATE_SIZE);
coords[i] = read_coords(line); //Put coordinates in coords
line = '\0';
}
return coords; // return coordinates
}
static int read_line ( FILE *fp, char *line, int max_length)
{
int i;
char ch;
/* initialize index to string character */
i = 0;
/* read to end of line, filling in characters in string up to its
maximum length, and ignoring the rest, if any */
for(;;)
{
/* read next character */
ch = fgetc(fp);
/* check for end of file error */
if ( ch == EOF )
return -1;
/* check for end of line */
if ( ch == '\n' )
{
/* terminate string and return */
line[i] = '\0';
return 0;
}
/* fill character in string if it is not already full*/
if ( i < max_length )
line[i++] = ch;
}
/* the program should never reach here */
return -1;
}
struct coord read_coords(char *line){ // Returns coordinates read from char *line
struct coord c;
char *x;
char *y;
x = malloc(sizeof(char)*MAX_COORDINATE_SIZE);
y = malloc(sizeof(char)*MAX_COORDINATE_SIZE);
int i = 0;
do{
x[i] = line[i]; //Get the x coordinate
i++;
}while(line[i] != ' ');
i++;
do{
y[i-2] = line[i];
i++;
}while(line[i] != '\0');
c.x = atoi(x)-1;
c.y = atoi(y)-1;
return c;
}
void init_board(int nrows, int ncols, struct cell ***board){
*board = malloc(nrows * sizeof(*board) + nrows * ncols * sizeof(**board));
//Now set the address of each row or whatever stackoverflow says
struct cell * const firstrow = *board + nrows;
for(int i = 0; i < nrows; i++)
{
(*board)[i] = firstrow + i * ncols;
}
for(int i = 0; i < nrows; i++){ //fill the entire board with pieces
for(int j = 0; j < ncols; j++){
(*board)[i][j] = new_cell(i, j, 0, 0);
}
}
}
void print_board(struct cell **board, int nrows, int ncols){
printf("--------------------\n");
for(int i = 0; i<nrows; i++){
for(int j = 0; j<ncols; j++){
if(board[i][j].pop == 1){
printf("%d ", board[i][j].age);
}else if(board[i][j].pop == 0){
printf(" ");
}else{
printf("\n\nERROR!");
exit(0);
}
}
printf("\n");
}
printf("--------------------");
printf("\n");
}
struct cell **start_game(FILE *fp, int nrows, int ncols){ //x,y are no of rows/columns, fn is filename
int n; // n is the number of populated cells specified in the seed
struct coord *coords = read_init(fp, &n); // get the list of coords to populate board with
struct cell **board;
init_board(nrows, ncols, &board); // Set up the board
populate_board(coords, &board, &n); //populate the cells specified in the seed
return board;
}
void populate_board(struct coord *coords, struct cell ***board, int *n){
for(int i = 0; i < *n; i++){
(*board)[coords[i].x][coords[i].y].pop = 1; //populate the cell
}
}
struct cell new_cell(int x, int y, int pop, int age){ //Return new populated or non-populated cell with specified coordinates
struct cell c;
c.pop = pop;
c.age = age;
return c;
}
The seed file:
4
3 6
4 6
5 6
5 7
EDIT:
The error message: Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
I shall add that if I add a line line = malloc(sizeof(char)*MAX_COORDINATE_SIZE+1) after the declaration of line in read_init, I still get the same error.
In read_init() :
struct coord *read_init(FILE *fp, int *n){
//...
char *line;
//...
for(int i = 0; i<(*n); i++) {
read_line(fp, line, MAX_COORDINATE_SIZE);
coords[i] = read_coords(line); //Put coordinates in coords
line = '\0'; // <<--- you set line to NULL here.
*line = 0; // this is what you wanted to do, is not necessary...
}
// ....
}
I get a weird bug.
I suggest asking some questions about the compiler output. We should never blindly ignore warnings, after all. Speaking of reading things, I think you're spending too long reading StackOverflow and not long enough reading K&R2e and doing the exercises. We'll come back to that.
In the read_line function, the program crashes on line[i++] = ch statement ... But here is the (for me) strange part: ... The read_line function has already successfully execute twice and got me the first two lines (4\n and 3 6\n) from the seed file
The C and C++ standards rationalise the concept of "undefined behaviour" for this class of errors that are computationally difficult to diagnose. In other words, because you made an error, the behaviour of your program is undefined. It isn't required that your malfunctioning code crash every time, as that would be defining the undefined; instead they leave this "undefined" and the first two times your erroneously code works (whatever that means), purely by coincidence that the uninitialised variable points somewhere accessible. Later on you assign line = '\0';, which changes line to be a null pointer, and then you try to assign into whatever that null pointer points at. That's more undefined behaviour.
How is this possible? How can line be initialized without me initializing it and then suddenly not be initialized anymore?
line isn't initialised; you're using it uninitialised, which happens to coincidentally work (but needs fixing), then you assign it to be a null pointer and dereference a null pointer (more UB that needs fixing). Such is the nature of undefined behaviour. Such is the nature of learning C by guessing. You need a book!
I shall add that if I add a line line = malloc(sizeof(char)*MAX_COORDINATE_SIZE+1) after the declaration of line in read_init, I still get the same error.
You need to fix all of the errors, not just the one. For assistance you could see the warnings/errors your compiler emits. I see more uninitialised access here:
char gens_string[MAX_GENERATIONS]; // <--- where's the initialisation??
// Snip
strncat(gens_string, argv[2], MAX_GENERATIONS); // Boom
There's some really sus code around this comment: //Now set the address of each row or whatever stackoverflow says ... and on that note I want to point out that there are some subtly toxic know-it-alls who answer questions despite having as many misunderstandings as you, a humble person, and so you shouldn't hope to get the same quality of education from StackOverflow as you would from K&R2e... but apparently I'd be toxic for pointing out the egomaniacs and suggesting decent resources to learn from, so that's none of my business 🙄🤷♂️ let's just let the sociopaths sabotage the education of everyone huh?
(*board)[i] = firstrow + i * ncols;
Look, there is no guarantee that this even compiles let alone that the address on the right has a suitable alignment to store the type of value on the left. Misaligned access causes more undefined behaviour, which may also work coincidentally rather than logically. Just as you've never seen alignment violations before, so too has the person who suggested you use this code. Assuming the alignment requirements for your implementation are satisfied by this code, we then have the same questions to raise here:
(*board)[i][j] = new_cell(i, j, 0, 0);
Your whole program needs remodelling around the declaration of board changing from struct cell **board to struct cell (*board)[ncols];, for example. It'll become much simpler, and a whole class of bugs related to alignment requirements will disappear. To see the extent of the simplification, here's what your init_board ought to look like:
void init_board(int nrows, int ncols, struct cell (**board)[ncols]){
*board = malloc(nrows * sizeof(*board));
// NOTE: I snipped the erroneous StackOverflow logic around the comment mentioned above; you don't need that crud because of the more suitable choice of type
for(int i = 0; i < nrows; i++){ //fill the entire board with pieces
for(int j = 0; j < ncols; j++){
(*board)[i][j] = (struct cell){ 0, 0 };
}
}
}
I need to have a dynamic array so I have used malloc in my code...However I don't know how to successfully free the memory afterwards. Somewhere in my code I believe I have a pointer re-assignment which leads to dangling pointer error (when i do child2=child1). Does anyone know how to free my mallocs properly? Thanks in advance.
My actual code is below:
typedef struct Edge//per solution
{
int label;//label
float weight;//energy of each edge
} edge;
// creating the chrom structure
typedef struct Chrom
{
edge **gene;
float fitness_score;
}
In one of my functions i have the following, where pop_size and num_nodes was previously calculated as 100 and 10 respectively.
Chrom* child1;
Chrom* child2;
//allocate memory of child
child1 = malloc(num_nodes * sizeof(child1));
child2 = malloc(num_nodes * sizeof(child2));
if(child1 == NULL||child2 == NULL)
printf("ERROR1: Memory allocation failed!");
for(x = 1; x <= num_nodes; x++)
{
child1[x].gene = malloc(num_nodes * sizeof(edge*));
child2[x].gene = malloc(num_nodes * sizeof(edge*));
if(child1[x].gene == NULL||child2[x].gene == NULL)
printf("ERROR2: Memory allocation failed!");
for(y = 0; y < num_nodes; y++)
{
child1[x].gene[y] = malloc(num_nodes * sizeof(edge));
child2[x].gene[y] = malloc(num_nodes * sizeof(edge));
if(child1[x].gene[y] == NULL||child2[x].gene[y] == NULL)
printf("ERROR3: Memory allocation failed!");
}
}
//do something...
for(i=0; i<pop_size; i++)
for(x=0; x<num_nodes; x++)
for(y=0;y<num_nodes;y++)
child2[i].gene[x][y].label=child1[i].gene[x][y].label;
free(child1);//can i free the memory like this?
free (child2);// will it automatically do all 'arrays'?
Also, must I first check if memory was allocated properly before freeing it?
child1 = malloc(num_nodes * sizeof(child1));
this is incorrect. You are allocating space for num_nodes pointers (child1 is a pointer to Chrom). You want to allocate space for num_nodes Chrom instances.
Change it to
child1 = malloc(num_nodes * sizeof(*child1));
First of all, you allocate space for Chrom pointers, not the space for Chrom structures so I am surprised that child1[x].gene works without crashing but to only answer the questions posed as comments in your code,
free(child1);//can i free the memory like this?
free (child2);// will it automatically do all 'arrays'?
child1 is an array of pointers and each of those pointers points to allocated memory which will be lost when you free(child1). I would free each pointer child1[x].gene first and then free child1. Same thing for child2.
This is probably close to what you want:
typedef struct Edge//per solution
{
int label;//label
float weight;//energy of each edge
} edge;
// creating the chrom structure
typedef struct Chrom
{
edge *gene; // changed from edge**
float fitness_score;
};
int main(void)
{
int num_nodes = 3;
int x;
struct Chrom* child1;
// if you want num_nodes Chrom entries
child1 = malloc(num_nodes * sizeof(struct Chrom));
// Allocating individual edges (I don't know why you declare edge** gene
// so I will assume that what you intended was edge* gene
for(x = 1; x <= num_nodes; x++)
{
child1[x].gene = (edge*)malloc(sizeof(struct Edge));
}
// deallocate your memory
for(x = 1; x <= num_nodes; x++)
{
free(child1[x].gene);
}
// free your array of Chroms
free(child1);
return 0;
}
Here is what the code could be if you want a 2D array of edegs within each Chrom; Also, there is a bug in my previous answer; x should be initialized to zero in the for loop rather than to 1 because this will cause an array index out of bounds and use lower-than instead of lower-than-or-equal. (WARNING: I only tested it slightly):
typedef struct Edge//per solution
{
int label;//label
float weight;//energy of each edge
} edge;
// creating the chrom structure
typedef struct Chrom
{
edge **gene;
float fitness_score;
};
int main(void)
{
int num_nodes = 3;
int num_edges_x = 2;
int num_edges_y = 3;
int x, j;
struct Chrom* child1;
// if you want num_nodes Chrom entries
child1 = malloc(num_nodes * sizeof(struct Chrom));
// Allocating 2D array of edges for each Chrom
// USE zero-based indexing.
for(x=0; x < num_nodes; x++)
{
child1[x].gene = (edge**)malloc(num_edges_x * sizeof(edge*));
// initialise you array of edges
for (j=0; j<num_edges_x; j++)
{
child1[x].gene[j] = (edge*)malloc(num_edges_y * sizeof(edge));
}
}
// Use a child1[x].gene[x][y]
child1[0].gene[0][0].label = 3;
child1[0].gene[0][0].weight = 7.2F;
printf("\nlabel: %d - weight: %f", child1[0].gene[0][0].label, child1[0].gene[0][0].weight);
child1[1].gene[0][0].label = 1;
child1[1].gene[0][0].weight = 12.4F;
printf("\nlabel: %d - weight: %f", child1[1].gene[0][0].label, child1[1].gene[0][0].weight);
child1[1].gene[1][0].label = 5;
child1[1].gene[1][0].weight = 112.6F;
printf("\nlabel: %d - weight: %f", child1[1].gene[1][0].label, child1[1].gene[1][0].weight);
// deallocate your memory
for(x =0; x < num_nodes; x++)
{
for (j=0; j<num_edges_x; j++)
{
free(child1[x].gene[j]);
}
free(child1[x].gene);
}
free(child1);
return 0;
}
I have the following structure im using to encode a PPM file with a message using steganography:
typedef struct{
char code[CODE_LENGTH];
COMMENT *commentPPM;
int width, height, max;
COLOR (*colorValues)[];
} PPM;
and the color:
typedef struct{
unsigned char red, green, blue;
} COLOR;
and method:
PPM *encode(char *text, PPM *img){
//tested
printf("entered encode\n");
PPM *newPPM;
newPPM = duplicate(img);
printf("duplicated ppm\n");
int x,y, currentChar, textLength;
textLength = strlen(text);
////
for(currentChar = x = y = 0; currentChar < textLength; currentChar++){
printf("the current character is %c\n", *(text+currentChar));
//between 1 and the width
x += (rand() % (newPPM->width -1)) + 1;
printf("generated %d for x\n",x);
if(x >= newPPM->width){
printf("%d is greater than width(%d)\n",x,newPPM->width);
x -= newPPM->width;
printf("%d is the new x\n", x);
y++;
printf("incremented y to be %d\n", y);
}
newPPM->colorValues[y][x].red = text[currentChar]; //error (1)
printf("changed the value of color[%d][%d].red, to be %d, which is %c\n",y,x, text[currentChar], text[currentChar]);
}
return newPPM;
}
How do you access for example "red" within the pointer to the 1d array seen at (1)?
Edit: I get the error message:
"error: invalid use of array with unspecified bounds
newPPM->colorValues[y][x].red = text[currentChar];"
Edit 2: I'm hearing that I cannot access the elements of colorValues in
typedef struct{
char code[CODE_LENGTH];
COMMENT *commentPPM;
int width, height, max;
COLOR (*colorValues)[];
} PPM;
as it hasn't got the width specified so i cant determine the offset. However I this is just a pointer to a flexible array member is getting assigned a type
ppmFile->colorValues = getColors(fd, ppmFile->width, ppmFile->height);
COLOR (*getColors(FILE *fd, int width, int height))[]{
COLOR (*colors)[width] = (COLOR(*)[width]) malloc(sizeof(COLOR[height][width]));
int i,j;
for(i = 0; i < height; i++) {
for(j = 0; j < width; j++) {
fscanf(fd,"%d %d %d", &colors[i][j].red, &colors[i][j].green, &colors[i][j].blue);
}
}
return colors;
}
which has got the width specified. So if I'm understanding correct when I am passing this back to be stored in the struct i am "losing" the offset (width). However When I am in the encrypt method, I have access to the width, height, and current x and y positions, surely there is a way of telling the compiler that this flexible array member has the offset of width,I did do this in the printColors method and it worked fine (see bellow), why cant I tell the compiler that the values stored in newPPM->colorValues have the offset of width?
void printColors(int width, int height, COLOR (*colors)[width]){
int n, j;
for(n = 0; n < height; n++) {
for(j = 0; j < width; j++) {
printf("%d %d %d\n", colors[n][j].red, colors[n][j].green, colors[n][j].blue);
}
}
}
is there a way of casting the newPPM->colorValues to tell it to have the offset width? Like I did with colors in printColors
You're probably getting an error like:
prog.c:10:14: error: subscript of pointer to incomplete type 'struct foo []'
thing->foos[0][0].bar;
~~~~~~~~~~~^
1 error generated.
For reference, the above is the output of compiling this code:
struct foo { int bar; };
struct baz {
struct foo (*foos)[];
};
int main () {
struct baz * thing;
thing->foos[0][0].bar;
return 0;
}
(Live)
What the compiler is trying to tell you is that it cannot compute the offset needed to access subsequent elements of the outer array. The reason is that it doesn't know the size of the array elements (as they're of incomplete type, that is lacking size information).
Basically, it's trying to compute (the following is a pseudo language, not C)
thing + offset(foos) + 0 * sizeof(struct foo[]) + 0 * sizeof(struct foo) + offset(bar)
but it can't because it doesn't know sizeof(struct foo[]).
The root of this issue is that your trying to have a pointer to a variable length array in the first place. Changing the member to
struct foo (*foos)[42];
"solves" this by giving the arrays dome size.
If you want a 2D array just make it 1D, appending all inner arrays. (Of course this works only if they're of the same size, i.e. if you want a rectangular 2D array)
struct foo * grid = malloc (sizeof (struct foo) * rows * columns);
// access using grid [c * rows + r]
You can access 2D data in a 1D array by calculating the array index formula yourself.
buf[ width*y + x ];
where width needs to be the stride in units of the buffer type.
I am writing a C program, in which I try to dynamically allocate a 2-dim array (or an array of arrays.) After the table is allocated I try to iterate over it, but it throws an error about illegal memory access and creates a coredump.
After some investigation I've found out a curious thing: the array I experiment with is 4x4, but when I set array[0][3] = 123; it sets both [0][3] and [1][0] positions to be 123. Exactly the same thing happens if I assign array[1][0] = 123;, as it sets both [0][3] and [1][0] to the rightside value. Similar assignment is done for any "border values", like [2][0] and [1][3]. I guess something must be wrong with my allocation, but I can't figure it out. I was pretty sure that this is the way to dynamically allocate multi-dim arrays and a bit of research confirmed it. Here is my code (I know it should be SSSCE but I can't provide it shorter and still show the problem):
typedef struct {
int rows;
int columns;
double **data;
} matrix;
matrix* allocateMatrix(int inputRows, int inputColumns) {
matrix *matrixPointer = calloc(1, sizeof(matrix));
matrixPointer->rows = inputRows;
matrixPointer->columns = inputColumns;
#ifdef DOUBLE
matrixPointer->data = calloc(inputRows, sizeof(double*));
#else
matrixPointer->data = calloc(inputRows, sizeof(float*));
#endif
if (matrixPointer->data == NULL) {
printf("Error - inputRows value appears to be wrong.");
return NULL;
}
int i, j;
for (i = 0; i < inputRows; i++) {
#ifdef DOUBLE
matrixPointer->data[i] = calloc(inputColumns, sizeof(double));
#else
matrixPointer->data[i] = calloc(inputColumns, sizeof(float));
#endif
if (matrixPointer->data[i] == NULL) {
printf("Error - inputColumns value appears to be wrong.");
return NULL;
}
}
matrixPointer->data[2][0] = 123; //TEST CODE;
return matrixPointer;
}
And some code to see the contents of such created array:
matrix *lol = allocateMatrix(4, 4);
int i, j;
for (i = 0; i < lol->rows; i++)
for (j = 0; j < lol->columns; j++)
printf("%f ", lol->data[i][j]);
Is my memory allocation wrong, or maybe some other issue I fail to see. I would be grateful for any suggestions or help. Thank you in advance.
typedef struct {
int rows;
int columns;
double **data;
} matrix;
This is the culprit. The DOUBLE macrodefinition was supposed to enable double precision through the code, but when the flag was not set the code still allocated double** data, causing possible segmentation faults. The correct code in this case should look like:
typedef struct {
int rows;
int columns;
#ifdef DOUBLE
double **data;
#else
float **data;
#endif
} matrix;