I meet a case that I want to have an array of pointers(M rows, N cols), each member of this array points to a float vector (L‑length). Could you tell me how to establish it? I hope I can establish it dynamically because I usually don't know M, N, and L at first and L may be different for difference vector.
My occasion is that I need to read Green function with different distance(NDIS) and depth(NDP). So I need to create something like *grn[NDP][NDIS]. then use each pointer of this array to point to a component of green function.
By the way, I think it's a little bit complex than setting a size known array of pointers. Do you think it's worth to use this type of data structure? I'm trying to write a program to deal with observation, which I usually unknown it's size.
However, it's ok for me to use a size-fixed array of pointers. If the total data is larger than the given size, I could ignore the over-sized part. But I'd hope to use them all.
You need to use the 2-d array and need to allocate it Dynamically, like this:
int i, j;
float **arr;
arr = malloc(sizeof(float*) * Size1); //1st array setup
for(i = 0; i < Size1; i++)
arr[i] = malloc(sizeof(float*) * Size2); // 2nd array setup at each element of 1st array
Now accessing it like this:
for(i = 0; i < Size1; i++)
for(j = 0; j < Size2; j++)
printf("%f", arr[i][j]);
Size1 & Size2 are sizes of first array and second array.
You can setup different sizes of individual arrays in first array elements, for that you need to do it without loop and by changing the Size2 variable.
Hope this helps.
Related
I am trying to shift the elements in a dynamically created 3d array by one index, so that each element [i][j][k] should be on [i+1][j][k].
This is how my array creation looks like
typedef struct stencil{
int ***arr;
int l;
int m;
int n;}matrix;
void createMatrix(matrix *vector){
vector->arr = (int***) malloc(sizeof(int**) * (vector->l+2));
for (int i = 0; i< vector->l+2; ++i) {
vector->arr[i] = (int**) malloc(sizeof(int*) * (vector->m+2));
for (int j = 0; j < vector->m+2; ++j) {
vector->arr[i][j] = (int*) calloc((vector->n+2),sizeof(int));
}
}
}
This is basically what I want to achieve with memmove
for(int i = vector->l-1; i >= 0; --i){
for(int j = vector->m; j >= 0; --j){
for(int k = vector->n; k >= 0; --k){
vector->arr[i+1][j][k] = vector->arr[i][j][k];
}
}
}
for some reason memmove shifts 2 indices.
memmove(&(vector->arr[1][1][1]), &(vector->arr[0][1][1]), (vector->l+2)*(vector->m+2)*(vector->n)*sizeof(int*));
Could anyone give me a hint?
When you create a dynamic multi-dimensional array like this, the array contents are not contiguous -- each row is a separate allocation. So you can't move it all with a single memmov().
But you don't need to copy all the data, just shift the pointers in the top-level array.
int **temp = arr[l-1]; // save last pointer, which will be overwritten
memmov(&arr[1], &arr[0], sizeof(*arr[1]));
arr[0] = temp;
I've shifted the last element around to the first, to avoid having two elements that point to the same data. You could also free the old last element (including freeing the arrays it points to) and create a new first element, but this was simpler.
Compile with a higher optimization level (-O3). Obtain a direct reference on vector->arr instead of forcing dereferencing on every single array access.
Your call to memmove looks half correct under the assumption that you allocated arr as continuous memory. However, since you said "dynamic", I very much doubt that. Plus the size calculation appears very much wrong, with the sizeof(int*).
I suppose arr is not int arr[constexpr][constexpr][constexpr] (single, continuous allocation), but rather int ***arr.
In which case the memmove goes horribly wrong. After moving the int** contents of the arr field by one (which actually already did the move), it caused a nasty overflow on the heap, most likely by chance hitting also a majority of the int* allocations following.
Looks like a double move, and leaves behind a completely destroyed heap.
Simply doing this would work (Illustrating in a 3d array)
memmove(arr[1], arr[0], Y*Z*sizeof(int));
where Y and Z denotes the other 2 dimensions of the 2d array.
Here arr[X][Y][Z] is the int array where X>=2.
In case of dynamically allocated memory you need to do each continuous chunk one by one. Then it would work.
I have to use a 3 dimensions array because I want to divide a pic into squares and store the average of the RGB of each square in my array.
I want it to be this size, tab[height][width][3],
so I did that:
i = 0; j = 0; k = 0;
float*** tab;
tab = malloc((hauteur+1)*sizeof(float*));
while(i <= hauteur){
tab[i] = malloc((largeur+1)*sizeof(float**) );
i++;
}
i = 0;
while(i <= hauteur){
j = 0;
while (j <= largeur){
tab[i][j] = malloc(3*sizeof(float***));
j++;
}
i++;
}
but I have a segfault after : tab[1][30][2];.
Is there a problem in my malloc?
It's strange because it doesn't segfault when I declare tab using:
tab[hauteur][largeur][3].
(Sorry: "hauteur" means "height" in French and "largeur" means "width".)
(If you think you need to check my whole function: http://pastebin.com/eqQXz8Ad; it's a writer for a JPEG file.)
Your types aren't right in your malloc calls. I'd suggest the following:
tab = malloc( (hauteur + 1) * sizeof *tab ); // sizeof (float **)
tab[i] = malloc( (largeur + 1) * sizeof *tab[i] ); // sizeof (float *)
tab[i][j] = malloc( 3 * sizeof *tab[i][j] ); // sizeof (float)
Given the declaration of tab, the following are all true:
Expression Type
---------- ----
tab float ***
*tab float **
tab[i] float **
*tab[i] float *
tab[i][j] float *
*tab[i][j] float
I usually recommend taking the sizeof of the target expression, rather than an explicit type; that way, if you ever change the type of tab (from float to double, for example), you never have to touch the malloc calls.
What you are crafting is basically an array of array of array of pointers to float, not a three dimensional array of floats.
You may want have a look at this Ambiguity in 2d array declaration in C. It works out a similar problem with a bidimensional array.
Maybe the solution for your problem can looks like:
float (*tab)[hauteur][largeur][3]; //declare a pointer to a real array
tab = malloc(hauteur * largeur * 3 * sizeof(float)); //Allocate room for threedimensional array
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
(*tab)[i][j][k] = (float)((i*100)+j*1000+k); //Fill elements with something using threedimensional subscripting
}
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
printf("[%d][%d][%d]=%f\n", i, j, k, (*tab)[i][j][k]); //Check back data...
}
EDITED
Looking at comments I see that it is someway 'unnatural' to access an array using the pointer to array notation (*array)[a][b]...[n] even if this notation explicitly report whole dimensions in declaration. To make more friendly the usage you can use the form below that allows the well known format:
#include <stdio.h>
#include <stdlib.h>
int largeur = 10;
int hauteur = 10;
int main(int argc, char *argv[])
{
float (*tab)[largeur][3]; //declare a bidimensional array of pointers to our variable
//this fools the compiler acting as a one more dimension array of variable
tab = malloc(hauteur * largeur * 3 * sizeof(float)); //Allocate room for threedimensional array
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
tab[i][j][k] = (float)((i*100)+j*1000+k); //Fill elements with something using threedimensional subscripting
//This use the natural addressing...
}
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
printf("[%d][%d][%d]=%f\n", i, j, k, tab[i][j][k]); //Check back data...
}
}
This kind of trick works because of the lack of multidimensional array concept in C language.
C knows only of array, or better it should have been string, of something, so a bidimensional array is simply an array of arrays of something. If we add one more dimension it is an array of an array of an array of something ... and so on for each more dimension we add.
This defines the memory layout of arrays in C and the addressing method that the compiler uses to access data. Because the data is streamed in memory to access a value at a specific subscript the compiler need to compute the space used for all dimensions but the very first.
+++ I fixed a bug, now the sample can be compiled under any C99-C11 compliant compiler and works.
If you care a lot about efficiency, you should consider having a single dimension array (like in Frankie_C's answer):
int height = something_to_compute_height();
int width = something_to_compute_width();
double *arr = malloc(height*width*3*sizeof(double));
if (!arr) { perror("malloc"); exit(EXIT_FAILURE); }
(as an aside, even if we both are native French speakers, let's try to use English in questions and code here)
then you might define a macro to ease speaking of some element inside arr
#define ELEM_ARR(a,i,j,k) a[i*width*height+j*width+k]
#define ARR(i,j,k) ELEM_ARR(arr)
(You've got the idea, details can be different)
This is probably more efficient than your array of pointers to array of pointers because of cache locality and because you need only one single allocation.
Choose carefully row-major or column-major access to fit the most frequent access patterns.
If height & width are specific to each array, you could use some flexible array member as last in a struct.
As a rule of thumb, it is useful in C to use multidimensional arrays only if all the dimensions (except perhaps the last) are a compile-time constant, e.g. double arr3d[3][4][5];; otherwise, better have a single-dimension array and do the index computing by yourself.
BTW, if you care a lot about performance, you might be concerned by OpenCL and OpenMP (and both usually prefer single-dimensional arrays).
So, I'm trying to create n identical arrays of the same size but with a slightly different name.
I cannot just define them individually as n depends on an input.
The only way I could think to do this is using a for loop, as shown below:
i=0;
for (j=0;j<n;j++){
int array_i[256];
i=i+1;
}
I was wondering if there's a way of allowing i to update name of array_i?
Or if there is just a better method to do this?
Thanks for any help
The way I would do it is by using a 2-dimensional array.
How to work with it:
int i, j; //counters
int array[n][256];
for (i=0; i<n; i++) {
for (j=0; j<256; j++) {
//enter code for element array[i][j] here
}
}
You can use ## operator which can paste two tokens together to form a single token, but not a good choice.
#define MAKE_ARR(n) array_##n
int MAKE_ARR(1)[256], MAKE_ARR(2)[256];
After preprocessing:
int array_1[256], array_2[256];
You need to declare a dynamic array to static arrays of size 256. Since you don't know in advance how many arrays there is you'll have to allocate them dynamically. Here is how you could do it.
int (*arrays)[256];
unsigned int i;
/* Reserve space for n arrays of 256 int elements */
arrays = malloc(sizeof(int) * 256 * n); /* or calloc() if you want it zeroed out */
/* Now you can access your arrays as if it was a normal 2D array */
arrays[i][j] = 42;
If and only if you can afford to use C99 variable lengths array, this is also possible :
int arrays[n][256];
Keep in mind that it will eat n * 256 * sizeof(int) bytes on the stack, so unless you can guarantee that n is a very small number (like 2 or 3) it is probably a bad idea to reserve that much space on the stack, doing it with malloc is cleaner/safer.
I am new to C and was writing a function to insert an element to sorted list. But my code does not display the last digit correctly. Though i know there are variety of ways to correct it but i want to know why my code isnt working, here's the code
#include <stdio.h>
int insert(int array[],int val);
int main (void)
{
int arr[5],j;
for (j = 0; j<5; j++)
{
scanf("%d",&arr[j]);
}
insert(arr,2);
for(j = 0;j<6;j++)
printf("%d",arr[j]);
return(0);
}
int insert(int array[],int val)
{
int k,i;
for (k = 0;k<5;k++)
if(val<array[k])
break;
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
}
array[k] = val;
return(1);
}
You are writing out of the range of the array here:
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
Where i+1 == 5 and you array has a range of 0 ...
4
Then you try to print the array but you go out of bounds again:
for(j = 0;j<6;j++)
printf("%d",arr[j]);
First make sure your array is large enough.
When you give a static / auto array to a function for insertion of elements, you must give: Address, Valid length, and Buffer Space unless guaranteed large enough.
When giving a dynamically allocated array, you must give pointer and valid length, you might give buffer space or guarantee enough space left to avoid reallocations.
Otherwise, you risk a buffer overrun, and UB means anything may happen, as in your example.
You're trying to make arr[6] out of arr[5] adding one val - it's impossible in C using statically allocated arrays.
To accomplish what you're trying to do you'd need to use dynamical arrays allocation:
int *arr;
int N = 5;
arr = (int *)malloc(N*sizeof(int));
then you use this arr same way as you did with arr[5] for loading data here via scanf.
And later on , while adding extra value to array - you'd need to reallocate your arr to make it bigger (read about malloc/realloc C functions):
arr = (int *)realloc((N+1)*sizeof(int));
Now your arr is of 6 int-s size.
Unfortunately if you don't know array sizes (number of elements) a priori you would need to deal with dynamical memory allocations in C.
Don't forget to release that memory in the end of the main() function:
free(arr);
You have to increase your array size from 5 to 6 as you are inserting one new element in your array, so there should be some space for that.
int arr[6];
you can also find more information in the link below:
https://learndswithvishal.blogspot.com/2020/06/insert-element-in-sorted-array.html
I cannot create a 2D array from 2 variables (eg int arr[i][j] not allowed) so how would I create a dynamically sized 2D array?
The dimensions of the array are only known at runtime in my program. The array is to represent a grid. How would I code this in C?
First allocate an array of pointers.
/* size_x is the width of the array */
int **array = (int**)calloc(size_x, sizeof(int*));
Then allocate each column.
for(int i = 0; i < size_x; i++)
{
/* size_y is the height */
array[i] = (int*)calloc(size_y, sizeof(int));
}
You can access the elements with array[i][j]. Freeing the memory is done in 'reverse' order:
for(int i = 0; i < size_x; i++)
{
free(array[i]);
}
free(array);
You have to allocate a 1-dimensional array:
int* array = calloc(m*n, sizof(int));
And access it like this:
array[i*n + j]
The compiler does exactly this when accessing two-dimensional arrays, and will probably output the same code when n can be guessed at compile time.
This is a FAQ on comp.lang.c (I took the liberty to add the c-faq tag), it even has a FGA (frequently given answer :-)
See http://c-faq.com/aryptr/index.html, 6.16 How can I dynamically allocate a multidimensional array?
In C a multidimensional array is just an array for which each element is another array.
So you need to first allocate memory for one array (the rows). You can use the malloc() function which will return a pointer to the array.
Then you iterate through the array and for each element you allocate memory for the number of columns.
NOTE: don't forget to free the memory you manually allocate with the free() function in the same way you used malloc() to allocate it.
Some of the examples show multiple (more than 2) allocations for the array; it is perfectly feasible to do it in just two allocations (error checking omitted) for an n × m array:
int **array = calloc(m, sizeof(*array));
int *data = calloc(m * n, sizof(*data));
for (int i = 0; i < m; i++)
array[i] = &data[i * n];
...use array[i][j]...
free(array[0]);
free(array);