I am trying to get a pointer to an array integers to be temporarily remapped in a function later on to save myself pointer math. I've tried to see if any other questions answered it, but I've been unable to reproduce the methods described here, here, and here.
Fundamentally, I just want to temporally treat an integer group and a 3D array to be sure that I don't mess up the pointer math. (I'm looking at this currently because the previous code had made inconsistent assignments to the memory).
#include <stdlib.h>
#define GROUPCOUNT 16
#define SENSORCOUNT 6
#define SENSORDIM 3
int main()
{
int *groupdata = (int *)calloc(GROUPCOUNT * SENSORCOUNT * SENSORDIM,sizeof(int));
int sensordata[SENSORCOUNT*SENSORDIM];
sensordata[7] = 42; //assign some data
int (*group3d)[GROUPCOUNT][SENSORCOUNT][SENSORDIM] = groupdata; //<---Here is the problem
group3d[1][5][1] = sensordata[7]; //I want to do this
free(groupdata);
}
In the example above, I want to handle groupdata as group3d temporarily for assignments, and I just cannot seem to wrap myself around the casting. I currently have macros that do the pointer math to enforce the correct structure, but if it was all just in the code, it would be even better when I pass it off. Any suggestions would be greatly appreciated.
note: The 3D cast is to be used in a function way in the bowels of the program. The example is just a minimally viable program for me to try to sort out the code.
When group3d is defined with int (*group3d)[GROUPCOUNT][SENSORCOUNT][SENSORDIM], then *group3d is a three-dimensional array. That would let you use it with (*group3d)[1][5][1].
To use it with group3d[1][5][1], you need group3d to be a pointer to a two-dimensional array:
int (*group3d)[SENSORCOUNT][SENSORDIM] = (int (*)[SENSORCOUNT][SENSORDIM]) groupdata;
(There are some technical concerns about C semantics in aliasing an array of int as an array of array of array of int, but this is not a problem in common compilers with default settings. However, it would be preferable to always use the memory as an array of array of array of int, not as an array of int.)
int l = 5, w = 10, h = 15;
int Data = 45;
int *k = malloc(l * w * h * sizeof *k);
// not use this k[a][b][c] = Data;
//use this is right
k[a*l*w + b*l + c] = Data;
In the example above, I want to handle groupdata as group3d
temporarily for assignments, and I just cannot seem to wrap myself
around the casting.
One possible solution is to create a multidimensional array dynamically like this. This way you won't have to cast things or worry about the dimensions.
int (*group3d)[GROUPCOUNT][SENSORCOUNT][SENSORDIM] = calloc(1, sizeof(int [GROUPCOUNT][SENSORCOUNT][SENSORDIM]));
(*group3d)[1][5][1] = sensordata[7]; //I want to do this
/* Then you can print it like */
printf("%d\r\n", (*group3d)[1][5][1]);
Related
I came across an old code where I need to allocate memory for an array of matrices. Currently it is done by creating a structure matrix and allocating memory by making an arrray of structures.
Like so.
struct matrix
{
int x[13][13];
};
int main()
{
matrix *push = (matrix*)malloc(sizeof(matrix) * 1000);
//do stuff
free(push);
return 0;
}
But now the question.. Do I really need to do this? I know I am allowed to declare a variable of type int *matrix[13][13];
But I cant seem to figure out a way to allocate memory to this variable.
I tried matrix = (int***)malloc(sizeof(int[13][13])*1000); which results in
E0137 expression must be a modifiable lvalue and honestly in doesnt seem correct either
I know there are many better and creative ways of allocating an array like this, but I am curious
Questions
int *matrix[13][13] what will this kind of variable even mean or represent? Is it a pointer to a 2D matrix or s it an pointer to an array of 2D matrices?
How will I use the above mentioned variable?
How will I allocate memory for the above variable without using any more variables?
Clarifications
From comments it seems int *matrix[13][13] represents a matrix of 13x13 int*
What I am asking is actually, is there a way to have a variable with a dynamically allocated first dimension and static 2nd and 3rd dimensions without using structures typedefs etc
EDIT
As pointed out by felix
what I am looking for is int (*matrix)[13][13] = (int(*)[13][13])malloc(1000*sizeof(matrix));
I have noticed that sometimes beginner programmers are finding typedef-ing the multidimensional matrices which have to be dynamically allocated easier as it reduces the problem to the single star pointer and the sizeof of the defined type and pointer to it is much easier to understand.
#include <stdio.h>
typedef int my13x13matrix[13][13];
int main(void) {
my13x13matrix *mylargematrix = malloc(1000 * sizeof(*mylargematrix));
mylargematrix[999][12][12] = 5;
printf("%d \n", mylargematrix[999][12][12]);
return 0;
}
you can also use the single star pointer arithmetic.
my13x13matrix *anotherpointer = &mylargematrix[10];
(*anotherpointer)[5][5] = 1;
anotherpointer++;
(*anotherpointer)[5][5] = 2;
printf("%d %d\n", mylargematrix[10][5][5], mylargematrix[11][5][5]);
No, you don't want to use
int *matrix[13][13];
That will declare a [13][13] array of int*s.
You need
// pointer to "an array of 13 x 13 ints"
int (*matrix)[13][13];
or simplify it by using a type alias.
typedef int matrix_type[13][13];
matrix_type* matrix_ptr;
You can allocate memory for such a variable using
matrix_type* matrix_ptr = malloc(1000*sizeof(*matrix_ptr));
and assign values to it using
matrix_ptr[0][0][0] = 0;
...
matrix_ptr[999][12][12] = 0;
I am trying my hand at C by implementing Conway's game of Life.
I am trying to dynamically build two grids (int matrices), one for the current and one for the next generation, so after I determine what the next generation looks like, I just swap pointers.
At first I tried hopelessly to define the pointer to the grid like int * grid, which you cannot subscript with a second set of brackets like [][] because - obviously - the first set of brackets returns an int.
I also tried something like int * grid[HEIGHT][WIDTH], but this gives problems assigning one pointer like this to another. (And in fact, I have no idea what this really does in memory!)
In my naïve hopefulness, I thought the following could work after stumbling across double pointers. The program compiles, but fails when running on the line indicated. (In Windows, I get no more detail other than that the Problem Event Name is APPCRASH).
DISCLAIMER: This is not the actual program, just a proof of concept for the problem.
#include <stdio.h>
#include <stdlib.h>
int HEIGHT = 20;
int WIDTH = 20;
int ** curr_gen; // Current generation
int ** next_gen; // Next generation
/* Entry Point main */
int main(int argc, char** argv) {
// Allocate memory for the grids
curr_gen = malloc(sizeof (int) * WIDTH * HEIGHT);
next_gen = malloc(sizeof (int) * WIDTH * HEIGHT);
curr_gen[0][0] = 0; //<< PROGRAM FAILS HERE
// Release heap resources
free(curr_gen);
free(next_gen);
return 0;
}
You can simply allocate the space and cast the pointer to the type which defines the col and row sizes. Looking up a pointer via [][] is expensive. And building a dynamic multi dimensional array this way should be reserved for ragid arrays.. IE: only use it when necessary.
You can define a type:
typedef int MyArray[20][20];
And then cast the malloc pointer to the type you want:
MyArray * curr_gen = (MyArray *) malloc(...);
However this assumes that you have a constant, known at compile time height and width. If it must be dynamic then by all means use the index into a pointer table method. But keep in mind that the actual pointer looked up must be loaded at the last possible minute leading to Pipeline stalls, and potential cache misses. Making it 100 times more expensive than just doing the math yourself via [row * 20 + col].
So the real question you should ask yourself is "Does it need to run fast, or do I want the code to look 'Neat'?"
A common way to do this is described in http://c-faq.com/aryptr/dynmuldimary.html
You can just use int* as the type of grid in my way.
Convert the 2D position to 1D by a macro define or a function:
#define MATRIX2INDEX(x, y, width) ((x) + (y) * (width)) // `width` is the max of x + 1 :)
int Matrix2Index(int x, int y, int width)
{
return MATRIX2INDEX(x, y, width);
}
Visit the data by 2D position in int*:
int* grid = (int*)malloc(sizeof(int) * WIDTH * HEIGHT);
grid[MATRIX2INDEX(0, 0, WIDTH)] = 0; // here: get the data you want by 2D position
free(grid); grid = NULL;
So I have the following:
int from[2][3] = { {1,2,3}, {2,3,4} };
int into[3];
into = memcpy(into, from[0], 3 * sizeof(*into));
I want to copy 'from' in to the array 'into' so that 'into' = { 1, 2, 3}
I am trying to do the above using memcpy (i know that it already works with a loop) but I cant seem to get it working.
I keep on getting the error :
error: incompatible types when assigning to type ‘int[3]’ from type ‘void *’
I found a link to this question:
How do I copy a one-dimensional array to part of another two-dimensional array, and vice-versa?
and changed my code (Above) but i still get the error.
I am still clueless, I have solved my problem in another manner but curiosity I would like to know how it is done as from the previous post I know it is possible.
As KingsIndian points out, you can avoid the problem by dropping the assignment, since you don't actually need the return value in this instance. However it may help for the future to understand what's going on under the hood:
memcpy returns a pointer to its destination. If "into" were a pointer, then it would be fine:
int from[2][3] = { {1,2,3}, {2,3,4} };
int into[3];
int *into_ptr = into;
into_ptr = memcpy(into_ptr, from[0], 3 * sizeof(int)); // OK
The problem is that "into" is an array, not a pointer. Arrays in C are not variables, i.e. they cannot be assigned to, hence the error. Although it's often said that arrays and pointers are equivalent, there are differences, this being one. More detail on the differences between arrays and pointers is given here:
http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c/
Edit:
To avoid the problem altogether by not doing any assignment, ignore the return value:
int from[2][3] = { {1,2,3}, {2,3,4} };
int into[3];
memcpy(&into[0], from[0], sizeof(into));
memcpy returns a pointer to the destination which you are trying to assign to an array. You can ignore the return value of memcpy.
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
What you probably want is:
memcpy(into, from[0], sizeof into);
This will copy the 3 elements of 4 bytes each ( sizeof into == 12 here) from from[0] to into.
EDIT: Thank you very much for your responses. I understand this properly now!
I am trying to learn more on C pointers. Tinkering around, I am questioning the difference between two actions I am using.
This code seems to work at first glance, but I am not sure of what's the difference, and if any of these two approaches is wrong in some way.
I'd like to know what's the difference between the two pieces of code, when I should I pass the adress, and when a pointer to an array?
Is any of the pieces wrong? If so, what would be the proper way?
having a simple struct grid pretty much like struct grid { int val; } (for demonstration purposes)
First piece of code. Passing address of the pointer to the array.
void set (mygrid *grid, int foo){
grid->bar = foo; //should this be '*grid->bar?' But this seems to work properly.
}
void main(){
int i;
int* array;
int max = 24;
array = malloc(sizeof(grid) * max);
for(i = 0; i < max; i++){
set(&array[i], 0);
}
}
Second piece of code. I am not entirely sure why this works, but the compiler doesn't output any warning.
I am supposed to be passing the pointer to the start of the array like this?
void set(mygrid *grid, int foo){
int i; int max = 24; //so this example code compiles :P
for(i = 0; i < max; i++){
grid[i].bar = foo;
}
}
void main(){
int* array;
int max = 24;
array = malloc(sizeof(grid) * max);
set(array, 0); //Why not &array?
}
Passing an array decays into a pointer that points to the first member of the array, just like &array[0].
In your second example, array is just a pointer, and the return value from malloc is just the address of the start of the block of memory you get.
It doesn't have to be used for an array; it could be used for storage of an arbitrary sizeof(int) * max bytes of data. An array (in C) is really just a nice way of thinking about & working with a solid block of memory divided up into equal size portions.
Secondly, you should understand how my_array[i] works. All it does is take the address of where your block of array data starts (which is the actual value of my_array), and then look at what value is stored at a particular offset from there. Specifically, if my_array is of a (made up) type of WhatEver, then it will access the data from my_array + i*sizeof(WhatEver) to my_array + (i+1)*sizeof(WhatEver).
On a related note (since you're learning C), it's highly recommended to check that the return from malloc is not NULL before doing anything with it.
I'm no C guru but am also trying to improve my understanding so if this is incorrect, please leave a comment or edit my answer so I can learn from my mistakes :)
In your first piece of code
grid->bar is same as (*grid).bar
. and using name of an array refers to its base address. so writing array is equivalent &array[0]
&array[i] is equivalent to array+i
array[i] is equivalent to *(array +i)
In you second piece of code i dont understand why there is no error because in your function set you do not declare max and i dont see a global max variable too.
also in your second piece of code you use
set(array,0) because array is already an integer pointer(see the declaration int * array).As far as i understand the mygrid is not a struct but is an array of structs in the second example
In C, an array is pretty much the same as a pointer. For me this isn't so amazing, since it is one of the earlier programming languages I learned, but if you're coming from a high level language where an array is a different type of object, then it might come across as strange.
I am working with a 2-dimensional array of structs which is a part of another struct. It's not something I've done a lot with so I'm having a problem. This function ends up failing after getting to the "test" for-loop near the end. It prints out one line correctly before it seg faults.
The parts of my code which read data into a dummy 2-d array of structs works just fine, so it must be my assigning array to be part of another struct (the imageStruct).
Any help would be greatly appreciated!
/*the structure of each pixel*/
typedef struct
{
int R,G,B;
}pixelStruct;
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
imageStruct ReadImage(char * filename)
{
FILE *image=fopen(filename,"r");
imageStruct thisImage;
/*get header data from image*/
/*make a 2-d array of of pixels*/
pixelStruct imageArr[thisImage.height][thisImage.width];
/*Read in the image. */
/*I know this works because I after storing the image data in the
imageArr array, I printed each element from the array to the
screen.*/
/*so now I want to take the array called imageArr and put it in the
imageStruct called thisImage*/
thisImage.arr = malloc(sizeof(imageArr));
//allocate enough space in struct for the image array.
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*/
//test to see if assignment worked: (this is where it fails)
for (i = 0; i < thisImage.height; i++)
{
for (j = 0; j < thisImage.width; j++)
{
printf("\n%d: R: %d G: %d B: %d\n", i ,thisImage.arr[i][j].R,
thisImage.arr[i][j].G, thisImage.arr[i][j].B);
}
}
return thisImage;
}
(In case you are wondering why I am using a dummy array in the first place, well it's because when I started writing this code, I couldn't figure out how to do what I am trying to do now.)
EDIT: One person suggested that I didn't initialize my 2-d array correctly in the typedef for the imageStruct. Can anyone help me correct this if it is indeed the problem?
You seem to be able to create variable-length-arrays, so you're on a C99 system, or on a system that supports it. But not all compilers support those. If you want to use those, you don't need the arr pointer declaration in your struct. Assuming no variable-length-arrays, let's look at the relevant parts of your code:
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
arr is a pointer to pixelStruct, and not to a 2-d array of pixels. Sure, you can use arr to access such an array, but the comment is misleading, and it hints at a misunderstanding. If you really wish to declare such a variable, you would do something like:
pixelStruct (*arr)[2][3];
and arr would be a pointer to an "array 2 of array 3 of pixelStruct", which means that arr points to a 2-d array. This isn't really what you want. To be fair, this isn't what you declare, so all is good. But your comment suggests a misunderstanding of pointers in C, and that is manifested later in your code.
At this point, you will do well to read a good introduction to arrays and pointers in C, and a really nice one is C For Smarties: Arrays and Pointers by Chris Torek. In particular, please make sure you understand the first diagram on the page and everything in the definition of the function f there.
Since you want to be able to index arr in a natural way using "column" and "row" indices, I suggest you declare arr as a pointer to pointer. So your structure becomes:
/* data for each image */
typedef struct
{
int height;
int width;
pixelStruct **arr; /* Image data of height*width dimensions */
} imageStruct;
Then in your ReadImage function, you allocate memory you need:
int i;
thisImage.arr = malloc(thisImage.height * sizeof *thisImage.arr);
for (i=0; i < thisImage.height; ++i)
thisImage.arr[i] = malloc(thisImage.width * sizeof *thisImage.arr[i]);
Note that for clarity, I haven't done any error-checking on malloc. In practice, you should check if malloc returned NULL and take appropriate measures.
Assuming all the memory allocation succeeded, you can now read your image in thisImage.arr (just like you were doing for imageArr in your original function).
Once you're done with thisImage.arr, make sure to free it:
for (i=0; i < thisImage.height; ++i)
free(thisImage.arr[i]);
free(thisImage.arr);
In practice, you will want to wrap the allocation and deallocation parts above in their respective functions that allocate and free the arr object, and take care of error-checking.
I don't think sizeof imageArr works as you expect it to when you're using runtime-sized arrays. Which, btw, are a sort of "niche" C99 feature. You should add some printouts of crucial values, such as that sizeof to see if it does what you think.
Clearer would be to use explicit allocation of the array:
thisImage.arr = malloc(thisImage.width * thisImage.height * sizeof *thisImage.arr);
I also think that it's hard (if even possible) to implement a "true" 2D array like this. I would recommend just doing the address computation yourself, i.e. accessing a pixel like this:
unsigned int x = 3, y = 1; // Assume image is larger.
print("pixel at (%d,%d) is r=%d g=%d b=%d\n", x, y, thisImage.arr[y * thisImage.width + x]);
I don't see how the required dimension information can be associated with an array at run-time; I don't think that's possible.
height and width are undefined; you might want to initialise them first, as in
thisImage.height = 10; thisImage.width = 20;
also,
what is colorRGB?
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*
This won't work. You have to declare arr as colorRGB **, allocate it accordingly, etc.
it looks like you are trying to copy array by assignment.
You cannot use simple assignment operator to do that, you have to use some function to copy things, for example memcpy.
*thisImage.arr = *imageArr;
thisimage.arr[0] = imagearr[0];
The above statements are doing the same thing.
However this is not most likely what causes the memory corruption
since you are working with two dimensional arrays, do make sure you initialize them correctly.
Looking at the code, should not even compile: the array is declared as one-dimensional in your image structure but you refer to as two-dimensional?