C Structure TriplePointer Memory Allocation - c

I have this two structures:
typedef struct {
unsigned int rows;
unsigned int cols;
Cell ***cells;
} Board;
typedef struct {
unsigned int info;
unsigned char state;
unsigned int mines;
} Cell;
initialized the board structure:
board = (Board*) malloc(sizeof(Board));
board->rows = 2;
board->cols = 2;
board->cells = NULL;
after that I call this function:
int initCells(Board **board) {
Cell **cells = (Cell**) malloc((*board)->rows * sizeof(Cell*));
for (int i = 0; i < (*board)->rows; i++) {
cells[i] = (Cell*) malloc((*board)->cols * sizeof(Cell));
}
(*board)->cells = &cells;
(*board)->cells[0][0]->info = 7;
(*board)->cells[0][1]->info = 7;
(*board)->cells[1][0]->info = 7; // segmentation fault
return 0;
}
Why do I get on the third segmentation fault and what would be the correct way to allocate memory to the triple pointer?

(*board)->cells = &cells;
This sets the board cells pointer to point to a local variable from the function. When the function returns that pointer is no longer valid.
It seems like yo have one pointer level too many. There is no reason I can see for the third level.
Also the second level on the board parameter just complicates things, but is is totally superfluous.

Related

Dynamically allocated struct in function

I have a school project related to bmp and im a bit stuck with the dynamic allocation aspect of things(as I have been asked to use that).
What im trying to do is pass my array using a pointer, so that the array changes its value even after the function ends,which is why i used **. However, the code just ends up crashing because of this single bit(as without it it runs smoothly).Im sure it's my use of * and & incorrectly but I don't know where and how to fix it.
typedef struct pixel{unsigned int r,g,b;}pixel;
void liniarizare(char *filename,pixel **liniar)
{int i;
... (i calculate size which is surely correct and declare fin;size=width*height*sizeof(pixel)
*liniar=(pixel*)malloc(size);
for (i=0;i<width*height;i++)
{fread(&liniar[i]->b,1,1,fin);
fread(&liniar[i]->g,1,1,fin);
fread(&liniar[i]->r,1,1,fin);
}
}
...
int main()
{...
pixel *liniar
liniarizare(filename,&liniar);
....}
Note that this is prefaced by my top comments.
That is, have the function return pixel *. And, use an extra unsigned char variable to prevent reading a byte into an unsigned int
Here's a simplified version that I think should work:
typedef struct pixel {
unsigned int r;
unsigned int g;
unsigned int b;
} pixel;
pixel *
liniarizare(char *filename)
{
int i;
int count = width * height;
int size = sizeof(pixel) * count;
pixel *liniar = malloc(size);
pixel *pix = liniar;
unsigned char byte;
for (i = 0; i < count; ++i, ++pix) {
fread(&byte,1,1,fin);
pix->b = byte;
fread(&byte,1,1,fin);
pix->g = byte;
fread(&byte,1,1,fin);
pix->r = byte;
}
return liniar;
}
int
main(void)
{
pixel *liniar;
liniar = liniarizare(filename);
return 0;
}
UPDATE:
Miraculously enough it works. The only problem is that i need to be able to pass the array by "reference" in the function and have the function provide back the modified array,which is why i insisted on using ** and a void. Do you have any idea what could be wrong in my code with your advice? You said something about linear[i]->b being wrong.
Okay, the simplest/best way to deal with a "return" double star argument (e.g.) whatever **retptr) is to ignore this as much as possible.
That is, the function deals with the simpler whatever *ptr internally. This is faster because there is only a single dereference level and not a double dereference on each statement.
The return value (i.e. the double star pointer) is only set at the end once.
Here's my example reworked to use your original function prototype [but with my other cleanup]. Note that only two lines are changed (the function prototype and the last line of the function):
typedef struct pixel {
unsigned int r;
unsigned int g;
unsigned int b;
} pixel;
void
liniarizare(char *filename,pixel **retval)
{
int i;
int count = width * height;
int size = sizeof(pixel) * count;
pixel *liniar = malloc(size);
pixel *pix = liniar;
unsigned char byte;
for (i = 0; i < count; ++i, ++pix) {
fread(&byte,1,1,fin);
pix->b = byte;
fread(&byte,1,1,fin);
pix->g = byte;
fread(&byte,1,1,fin);
pix->r = byte;
}
*retval = liniar;
}
int
main(void)
{
pixel *liniar;
liniarizare(filename,&liniar);
return 0;
}
Sometimes the "return value" pointer needs to be read at the top of a function and set at the bottom.
Here's a "push to tail" function for a singly linked list:
void
push(node **list,node *new)
{
node *head;
node *prev;
node *cur;
head = *list;
prev = NULL;
for (cur = head; cur != NULL; cur = cur->next)
prev = cur;
if (prev != NULL)
prev->next = new;
else
head = new;
new->next = NULL;
*list = head;
}
UPDATE #2:
Okay, now that we've got something working, it's time to optimize it [after a suitable rest period :-)].
Keep the now working version around as a reference/cross-check.
fread calls on single bytes are somewhat expensive.
Since your code is doing byte at a time I/O, we can replace the fread calls with fgetc. This should be slightly faster:
for (i = 0; i < count; ++i, ++pix) {
pix->b = fgetc(fin) & 0xFF;
pix->g = fgetc(fin) & 0xFF;
pix->r = fgetc(fin) & 0xFF;
}
However, we'd like to read as much as we can in single chunk. To read the entire image in one fread call would require a temp array of (e.g.) unsigned char image[count];. This is probably too much memory, and reading a large image might run into cache hit/miss issues.
But we could do a row at a time (e.g. unsigned char row[width * 3];). This is more tractable and probably produces as good or better results, so it may be a good compromise.
This may or may not be faster. That's why we keep the other versions around and benchmark to determine the fastest/best.
Note that this code assumes that pixels in the X dimension are physically adjacent [a reasonable possibility], but still works even if the matrix is transposed. In the end, it still reads count pixels in linear order, per your original code:
typedef struct pixel {
unsigned int r;
unsigned int g;
unsigned int b;
} pixel;
void
liniarizare_by_row(char *filename,pixel **retval)
{
int i;
int yidx;
int count = width * height;
int size = sizeof(pixel) * count;
int w3 = width * 3;
pixel *liniar = malloc(size);
pixel *pix = liniar;
unsigned char row[w3];
for (yidx = 0; yidx < height; ++yidx) {
fread(row,sizeof(row),1,fin);
for (i = 0; i < w3; i += 3, ++pix) {
pix->b = row[i + 0];
pix->g = row[i + 1];
pix->r = row[i + 2]
}
}
*retval = liniar;
}
int
main(void)
{
pixel *liniar;
pixel *liniar_fast;
liniarizare(filename,&liniar);
liniarizare_fast(filename,&liniar_fast);
return 0;
}

C language error: request for member ‘value’ in something not a structure or union

I got really confused why I can not use while loop to access the entire value for reading all of struct...Thank you guys... I think about 3 hours but have no clue. I do not know why does the value is not realized by the program, since I already defined that this is a struct.
#include <stdio.h>
struct card{
int isRed;
int hasLetter;
union{
int charValue;
int intValue;
}value;
};
typedef struct card typeCard;
int deckValue(typeCard *deck[])
{
int i = 0;
int sum = 0;
while(deck[i] != NULL){
sum += deck[i].value.intValue;
i += 1;
}
return sum;
}
int main()
{
int sum;
typeCard card1 = {.isRed = 1,.hasLetter = 0,.value.intValue = 200};
typeCard card2 = {.isRed = 100,.hasLetter = 0,.value.intValue = 200};
typeCard deck[] = {card1,card2,NULL};
sum = deckValue(deck);
printf("%d",sum);
return 0;
}
The problem is that the parameter to your function:
int deckValue(typeCard *deck[])
Doesn't match how you're using it:
sum += deck[i].value.intValue;
The function definition says that desk is an array of pointers to typeCard. So when you do deck[i].value it thinks that you have an array of typeCard.
You instead want:
sum += deck[i]->value.intValue;
This will dereference the pointer for the array element.
Also in main, you're not passing an array of pointers to typeCard:
typeCard deck[] = {card1,card2,NULL};
sum = deckValue(deck);
You're passing an array of typeCard. Since you want an array of pointers so you can use a NULL pointer as a sentinel, you need to change the definition to an array of pointers, and initialize the array elements accordingly:
typeCard *deck[] = {&card1, &card2, NULL};

C- Iterating over an array of structs passed through a void*

I have a function
struct Analysis reduce (int n, void* results)
Where n is the number of files to be analyzed, and I'm passing an array of Analysis structs to results.
The Analysis struct is defined as follows:
struct Analysis {
int ascii[128]; //frequency of ascii characters in the file
int lineLength; //longest line in the file
int lineNum; //line number of longest line
char* filename;
}
I've cast the void * as such,
struct Analysis resArray[n];
struct Analysis* ptr = results;
resArray[0] = ptr[0];
but I can't figure out how to iterate through the resArray properly. I've tried
for (i = 0; i < n; i++){
printf("lineLength: %d\n", resArray[i].lineLength);
}
with n = 3, and I'm getting garbage values. resArray[0] is correct, but resArray[1] is an insanely high number and resArray[2] is just 0. Why wouldn't resArray[1] or resArray[2] give the correct values? If I was incrementing the address incorrectly then it would make sense but I'm just accessing the array at a certain index. Pretty lost here!
resArray[0] is correct because there is "something":
resArray[0] = ptr[0];
Other elements are garbage because you didn't set there any values. If you want to copy entire array you need to change copying method to:
for (i = 0; i < n; i++)
{
resArray[i] = ptr[i];
}
You can't assign a pointer to an array directly because they are different typessince array[n] is type struct analysis(*)[n] and ptr is type struct analysis(*). Check here for more info.
Hopefully this code will help you.
#include <stdio.h>
#define d 3
struct Analysis {
int ascii[128];
int lineLength;
int lineNum;
char *filename;
};
struct Analysis Analyses[d];
struct Analysis reduce(int n, void *results) {
struct Analysis resArray[n];
struct Analysis *ptr = results;
for (int i = 0; i < n; i++) {
resArray[i] = ptr[i];
}
for (int i = 0; i < n; i++) {
printf("lineLength: %d\n", ptr[i].lineLength);
}
return *ptr;
}
int main(void) {
struct Analysis a = {{5}, 2, 2, "George"};
struct Analysis b = {{6}, 3, 3, "Peter"};
struct Analysis c = {{7}, 4, 4, "Jane"};
Analyses[0] = a;
Analyses[1] = b;
Analyses[2] = c;
reduce(d, &Analyses);
return 0;
}
You can try it online.

LED matrix pattern manipulation with a byte matrix

I'm with few questions about how to implement a function for adding a byte matrix to some "pattern" structure vector.
Here is my code structure:
struct pattern<br>
{
byte** map;
int size;
};
struct pattern* pvec;
int patterns = 0;
void add_pattern(byte** map, int size)
{
struct pattern p;
int i;
p.size = size;
p.map = (byte**) malloc(p.size * sizeof(byte*));
for (i = 0; i < size; i++)
p.map[i] = (byte*) malloc(4 * sizeof(byte));
p.map = map;
pvec[patterns] = p;
patterns++;
}
And an example of a byte matrix:
{
{B1000,B0000,B0000,B0000},
{B0100,B0000,B0000,B0000},
{B0010,B0000,B0000,B0000},
{B0001,B0000,B0000,B0000},
{B0000,B0001,B0000,B0000},
{B0000,B0000,B0001,B0000},
{B0000,B0000,B0000,B0001},
{B0000,B0000,B0000,B0010},
{B0000,B0000,B0000,B0100},
{B0000,B0000,B0000,B1000},
{B0000,B0000,B1000,B0000},
{B0000,B1000,B0000,B0000}
}
But I think this isn't a good way to do that, because I don't know exactly how to send this byte** argument to the function, considering that I have some patterns with few "rows of bytes" than others.
How can I do this in another way? Maybe sending a pre-built pattern structure as an argument?

using malloc for block of structs

I am trying to allocate a block of memory, and store a list of structures without using multiple mallocs for each... this is just a generic example, I don't have the original code I was working with earlier, but this is the general idea, but my problem was that I was getting heap corruption when other parts of my code executed after the InitPoints() function call. I don't know what part of my code is illegal, but I suspect it is in the for loop of the InitPoints() function. I am trying to use this as table, then I can create additional tables of defined size if I ran out of memory and link them together... so kind of like a dynamic expanding array if that makes any sense.
typedef struct Tb{
POINT points;
POINT *next;
} TABLE;
typedef struct Pt{
int x;
int y;
}POINT;
POINT *mypoints;
int main() {
int size = 10;
int i = 0;
mypoints = InitPoints(size);
for(i=0; i < size; i++)
{
printf("mypoint [%d] = (%d,%d)\n",i, mypoints->x, mypoints->y);
mypoints = mypoints + sizeof(POINT);
}
// some other code...
// i.e. createThread(....)
return 0;
}
POINT* InitPoints(int size)
{
POINT *tmp;
POINT *orig;
int a = 10;
int b = 1000;
orig = (POINT*) malloc (sizeof(POINT) * size);
if(orig == NULL)
return NULL;
tmp = orig;
for (i = 0; i < size; i++)
{
tmp->x = a++;
tmp->y = b++;
tmp = tmp + sizeof(POINT);
}
return orig;
}
This is wrong:
mypoints = mypoints + sizeof(POINT);
You should review pointer arithmetic in C. Just use:
mypoints += 1; /* or something similar */
(There is a similar problem in your InitPoints function)
Here's one referemce:
http://www.eskimo.com/~scs/cclass/notes/sx10b.html
The problem is in this line:
tmp = tmp + sizeof(POINT);
It should be
++tmp;
The latter says to increment the pointer by one element; since it points to the structure, it increments by the size of the structure. The original code instead increments by n elements where n is the number of bytes in the structure. For example, if int is 32-bits, it will advanced by 8 elements.
This is why I would do it
for (i = 0; i < size; i++)
{
orig[i].x = a++;
orig[i].y = b++;
}
In C, adding an integer to a POINT* pointer advances the pointer not by that number of bytes, but by that number of POINT structures.
You have two places in your code where you add sizeof(POINT) to your pointer. Instead you should just add 1.

Resources