I have a question about how memory is allocated when I calloc. I had a look at this question, but it doesn't address how memory is allocated in the case of a dynamically allocated two dimensional array.
I was wondering if there was a difference in the memory representation between the following three ways of dynamically allocating a 2D array.
Type 1:
double **array1;
int ii;
array1 = calloc(10, sizeof(double *));
for(ii = 0; ii < 10; ii++) {
array1[ii] = calloc(10, sizeof(double));
}
// Then access array elements like array1[ii][jj]
Type 2:
double **array1;
int ii;
array1 = calloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
Type 3:
double **array1;
int ii;
array1 = malloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
From what I understand of calloc and malloc, the difference between the last two is that calloc will zero all the elements of the array, whereas malloc will not. But are the first two ways of defining the array equivalent in memory?
Are the first two ways of defining the array equivalent in memory?
Not quite. In the second type they are almost certainly contiguous, while in the first type this is not sure.
Type 1: in-memory representation will look like this:
+---+---+---+---+---+---+---+---+---+---+
double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+---+---+
^
|------------------------------------
. . . . . . . . | // ten rows of doubles
-
+---+---+---+---+---+---+---+---+---+--|+
double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0||
+---+---+---+---+---+---+---+---+---+--|+
^ . . . -
| ^ ^ ^ . . . . . |
| | | | ^ ^ ^ ^ ^ |
+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+
array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | // each cell points to ten doubles
+---+---+---+---+---+---+---+---+---+---+
^
|
|
+-|-+
array1| | |
+---+
Type 2: in-memory representation will look like this:
+---+---+---+---+---+---+---+---+---+---+ +---+
double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 |
+---+---+---+---+---+---+---+---+---+---+ +---+
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | | | | |
| | | | | | | | | | |
+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+ +-|-+
array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... |99 | // each cell points to one double
+---+---+---+---+---+---+---+---+---+---+ +---+
^
|
|
+-|-+
array1| | |
+---+
Simple Example
#include<stdio.h>
#include<stdlib.h>
int **d ;
int sum();
//----------------------------------------------
int main(){
d = (int **)calloc(3,sizeof(int*));
printf("\n%d",sum());
}
//-----------------------------------------------
int sum(){
int s = 0;
for(int i = 0; i < 3; i++)
d[i] = (int *) calloc (3,sizeof(int));
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
d[i][j] = i+j;
s += d[i][j];
printf("\n array[%d][%d]-> %d",i,j,d[i][j]);
}
}
return s;
}
In the first way, you allocate 10 pointers to double, and 100 double. In the second way you allocate 100 pointers to double.The other difference is that in the second way, you allocate one big block of memory, so that all the elements of your array are in the same block. In the first way, each "row" of your array is in a different block than the others.
Though, in the second way, your array should be a double* instead of a double**, because in this way of allocating, your array only contains pointers to double, not double.
On the case 1, you make:
array1[0] -> [memory area of 10]
array1[1] -> [memory area of 10] ...
array1[N] -> [memory area of 10] ...
Note: You cannot assume that the memory area is continuous, there might be gaps.
On the case 2 you make:
array1 -> [memory area of 100]
The case 3 is same as the case 2, but its not initializing the memory. Difference between case 1 and 2 & 3 is that on the first case you really have 2D memory structure. For example if you want to swap rows 1 and 2, you could just swap the pointers:
help = array1[1]
array1[1] = array1[2]
array1[2] = help
But if you want to do the same in the 2&3 case you need to do real memcpy. What to use? Depends what you are doing.
The first way uses bit more memory: if you would have array of 1000x10 then the first version will use 1000*8 + 1000*10*8 (on 64bit system), while the 2&3 will only use 1000*10*8.
Related
I am currently trying to convert an equation into simpler form and found out that my codes are over writing the value at the end of the loop.
I have found out similar discussions but not exactly what I am looking for. Most of articles were using other languages so I couldn't get the answer.
Any answers are appreciated and thanks in advance.
followings are my code
int index = 0;
int result = 0;
char tresult[100];
char *equation[100] = { NULL, };
char *temp = strtok(input, " ");
for(int i = 1; i < x; i = i + 2)
{
char *temp_sign = equation[i];
if(*temp_sign == '*')
{
result = atoi(equation[i - 1]) * atoi(equation[i +1]);
sprintf(tresult, "%d", result);
equation[i - 1] = tresult;
sprintf(equation[i], "%d", 0);
sprintf(equation[i + 1], "%d", 0);
}
}
for(int j = 0; j < x; j++)
{
printf("%s ", equation[j]);
}
Expected input
5 * 3 + 1 * 2
targeted output
15 0 0 + 2 0 0
I will remove 0 by adding extra codes to make it as
15 + 2
but currently, my output looks like
2 0 0 + 2 0 0
When I print out the value in the loop, all the values were correctly shown. What may be the cause of such problem?
It might be easier to understand if we draw out the pointer instead.
Assuming that input is initially equal to "5 * 3 + 1 * 2", then after the loop equation will look something like this:
+-------------+
| equation[0] | ------------------------\
+-------------+ |
| equation[1] | --> | input[2] | ... | | +------------+-----+
+-------------+ >--> | tresult[0] | ... |
| equation[2] | --> | input[4] | ... | | +------------+-----+
+-------------+ |
| equation[3] | ------------------------/
+-------------+
| equation[4] | --> | input[10] | ... |
+-------------+
| equation[5] | --> | input[12] | ... |
+-------------+
As seen in the above "drawing" both equation[0] and equation[3] will be pointing to the first character of the single array tresult.
And tresult will always contain the contents last written into it with sprintf(tresult, "%d", result). Which in your example will be "2".
I want to realloc 2d pointer array. It must be dynamic as follows ascii
+=====+==============+==============+==============+==============+======+
| | [0] | [1] | [2] | [3] | [..] |
+=====+==============+==============+==============+==============+======+
| [0] | 'a' | 'b' | 'c' | 'd' | |
+-----+--------------+--------------+--------------+--------------+------+
| [1] | object[0][0] | object[1][0] | object[2][0] | object[3][0] | |
+-----+--------------+--------------+--------------+--------------+------+
| [2] | object[0][1] | object[1][1] | object[2][1] | object[3][1] | |
+-----+--------------+--------------+--------------+--------------+------+
| [3] | object[0][2] | object[1][2] | object[2][2] | | |
+-----+--------------+--------------+--------------+--------------+------+
| [4] | object[0][3] | | object[2][3] | | |
+-----+--------------+--------------+--------------+--------------+------+
| [5] | object[0][4] | | | | |
+-----+--------------+--------------+--------------+--------------+------+
| [6] | object[0][5] | | | | |
+-----+--------------+--------------+--------------+--------------+------+
In this table every cols size is different. How can i do this with 2d struct. I allocated matrix with malloc. But i want to realloc second index. Like this matrix[25][n]. N must be realloc for every column with different size. But it must be on runtime
Code :
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char word[20];
}Dictionary;
Dictionary **object;
void initializeDictionary()
{
// Create matrix [29][1]
object=(Dictionary**)malloc(29 * sizeof(Dictionary*));
object[0]=(Dictionary*)malloc(1*sizeof(Dictionary));
}
With pointers this comes naturally. In your code you have a Dictionary** which indeed is a pointer to pointer to Dictionary. But you can see it an array of Dictionary* in which each pointer points to a different sized array of Dictionary objects.
Dictionary** objects;
const int COLUMNS = 29;
objects = malloc(COLUMNS * sizeof(Dictionary*));
objects[0] = malloc(2 * sizeof(Dictionary)); // first column 2 elements
objects[1] = malloc(3 * sizeof(Dictionary)); // second column 3 elements
// ...
for (int i = 0; i < COLUMNS; ++i)
free(objects[i]);
free(objects);
Lets say we have this:
int main()
{
int32_t* value = (uint32_t*)malloc(sizeof(uint32_t));
uint32_t array[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
*value = *(uint32_t*)((char*)array + 8);
printf("Value is: %d\n", *value);
return 0;
}
The value in this case would be 3.
Why exactly is that?
If we cast an uint32_t to char, does that mean one char is 4 Byte in uint32_t and therefore
array[9] = {0, 4, !!8!!, 12, 16, 20, 24, 28, 32};
Could someone try to explain this?
When you initialize an array, each initializer sets an element of the array regardless of how many bytes each element takes up.
You machine is probably using little-endian byte ordering. That means that array looks like this in memory:
-----------------------------------------------------------------
| 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 4 | 0 | 0 | 0 | ...
-----------------------------------------------------------------
| [0] | [1] | [2] | [3] | ...
Each value of type uint32_t is 4 bytes long with the least significant byte first.
When you do (char*)array that casts array (converted to a pointer) to a char *, so any pointer arithmetic on a char * increases the address by the size of a char, which is 1.
So (char*)array + 8 points here:
(char*)array + 8 ------------------
v
-----------------------------------------------------------------
| 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 4 | 0 | 0 | 0 | ...
-----------------------------------------------------------------
| [0] | [1] | [2] | [3] | ...
That pointer is then converted to a uint32_t * and dereferenced, so it reads the value 3.
You created array[9] takes 36 bytes. It stores in memory as shown in first row. 3 store as I represented(It varies from compiler).
After you typecast it into char memory is seen as shown in 2nd row.
Now if you add 8 it will go to 8th position that mean after 02, why because, (char*)array + 8 treated as type+8. Here type is char. So it moves only 8 bytes.
Then memory from 8 to 35 type cased to uint32_t and first value stored in *value. So it will 3 only.
typedef struct arg_struct {
struct GPU_FFT *fft;
struct GPU_FFT_COMPLEX *base;
float **input;
float *output;
int number;
} arg_struct;
...
arguments[0].input = **Queue;
arguments[1].input = *(*(Queue)+QueueSize[0]);
My multidimensional array is Queue[2][1025]. I am trying to pass Queue[0][0] and Queue[1][0] into my arguments structure. It gives me "error: incompatible types when assigning to type ‘float **’ from type ‘float’" error. As a rookie programmer, I've tried so many variations but still couldn't figure out how to pass them.
By the way, QueueSize[0] is an integer which has value of 1025.
You can solve your problem very easily, by making the input member a simple pointer:
float *input;
Then you can make each pointer point to the corresponding array of Queue:
arguments[0].input = Queue[0];
arguments[1].input = Queue[1];
Be careful though, the lifetime of Queue must be at least as long as the lifetime of arguments. If Queue goes out of scope then the pointers will be stray, and can no longer be used. If Queue can go out of scope then you need to create full arrays of (or allocate memory for) the input member, and copy the contents into that memory.
There is big difference between 2d array and pointer to pointer.
In your struct is pointer to pointer, so you have to init it like
arguments[0].input = malloc(sizeof(float *) * num_of_rows);
for (int i = 0; i < num_of_rows; i++)
{
arguments[0].input[i] = malloc(sizeof(float) * num_of_cols);
}
Dont forget to free all the allocated memory. You can use valgrind for checking memory leaks.
2D array is sequence of bytes in memory
0 1 2 3
+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 // begins on address 1000
+---+---+---+---+
| 0 | 0 | 0 | 0 | 1 // begins on address 1004
+---+---+---+---+
| 0 | 0 | 0 | 0 | 2 // begins on address 1008
+---+---+---+---+
| 0 | 0 | 0 | 0 | 3 // begins on address 1012
+---+---+---+---+
while array of pointers, where every pointer can point to another part of memory
0 1 2 3
+---+---+---+---+
| * | * | * | * |
+---+---+---+---+
| | | |
| | | | 0 1 2 3
| | | | +---+---+---+---+
| | | -> | 0 | 0 | 0 | 0 | // begins on address 1000
| | | +---+---+---+---+
| | -----> | 0 | 0 | 0 | 0 | // begins on address 2
| | +---+---+---+---+
| ---------> | 0 | 0 | 0 | 0 | // begins on address 3045
| +---+---+---+---+
-------------> | 0 | 0 | 0 | 0 | // begins on address 128
+---+---+---+---+
I want to create an integer array[5][10] using malloc(). The difference between memory address of array[0] and array[1] is showing 8. Why?
#include <stdio.h>
#include <stdlib.h>
int main() {
int *b[5];
for (int loop = 0; loop < 5; loop++)
b[loop] = (int*)malloc(10 * sizeof(int));
printf("b=%u \n", b);
printf("(b+1)=%u \n", (b + 1));
printf("(b+2)=%u \n", (b + 2));
}
The output is:
b=2151122304
(b+1)=2151122312
(b+2)=2151122320
The difference between memory address of array[0] and array[1] is showing 8. Why?
That's because sizeof of a pointer on your platform is 8.
BTW, use of %u to print a pointer leads to undefined behavior. Use %p instead.
printf("(b+1)=%p \n",(b+1));
printf("(b+2)=%p \n",(b+2));
Difference between array of pointers and a 2D array
When you use:
int *b[5];
The memory used for b is:
&b[0] &b[1] &b[2]
| | |
v v v
+--------+--------+--------+
| b[0] | b[1] | b[2] |
+--------+--------+--------+
(b+1) is the same as &b[1]
(b+2) is the same as &b[2]
Hence, the difference between (b+2) and (b+1) is the size of a pointer.
When you use:
int b[5][10];
The memory used for b is:
&b[0][0] &b[1][0] &b[2][0]
| | |
v v v
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ ...
| | | | | | | | | | | | | | | | | | | | | ...
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ ...
(b+1) is the same as &b[1], The value of that pointer is the same as the value of &b[1][0] even though they are pointers to different types.
(b+2) is the same as &b[2], The value of that pointer is the same as the value of &b[2][0]
Hence, the difference between (b+2) and (b+1) is the size of 10 ints.
First, with int *b[5] you are not creating a two dimensional array, but an array of pointers.
The elements of the array b are pointers. Each occupies the size of a pointer, which depends on your architecture. In a 64-bits architecture it will probably occupy 64 bits (8 bytes). You can check that by printing sizeof(int*) or sizeof(b[0])
Memory allocation will look like
b
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[0]+--------------> | | | | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[1]+--------------> | | |....... | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[2]+--------------> | | | ...... | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[3]+--------------> | | | ...... | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[4]+--------------> | | | ...... | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
b will point to b[0], after decay, and b + 1 will give the address of b[1]. Size of pointer on your machine is 8 bytes, therefore you are getting a difference of 8 in the address.
Beside of this
Do not cast return value of malloc
b[loop]=malloc(10*sizeof(int));
and use %p for pointer data type
printf("b=%p \n",(void *)b);
printf("(b+1)=%p \n",(void *)(b+1));
printf("(b+2)=%p \n",(void *)(b+2));
What you've declared is not technically a two dimensional array but an array of pointers to int, each of which points to an array of int. The reason array[0] and array[1] are 8 bytes apart is because you have an array of pointers, and pointers on your system are 8 bytes.
When you allocate each individual 1 dimensional array, they don't necessarily exist next to each other in memory. If on the other hand you declared int b[5][10], you would have 10 * 5 = 50 contiguous integers arranged in 5 rows of 10.