I have the following piece of code in C:
double ***grid
grid = calloc(nx, sizeof(double**))
for (int i = 0; i < nx; ++i) {
grid[i] = calloc(ny,sizeof(double*));
for (int j = 0; j < ny; ++j) {
grid[i][j] = calloc(nz,sizeof(double));
}
}
What I don't understand is that why can't we write grid[i]=calloc(ny,sizeof(double**))? Isn't it true that each member of grid is a "pointer to pointer"? Also shouldn't we have grid[i][j] = calloc(nz,sizeof(double*))?
The code works fine when I use grid[i][j][k]in its current form but I'm confused about why. I'm new to C, so I'd appreciate all forms of explanation.
EDIT: one line was missing: grid = calloc(nx, sizeof(double**))
First you're missing the first alloc: grid = calloc(nx, sizeof(double **)); but I'm not sure this is the point since the code does not even compile (missing semicolon after grid declaration so it must have been allocated somewhere else)
Then to answer your question, allocation returns a pointer on the object, which adds an extra *, but you have to specify the size of the element for calloc to make the calculations (ny*sizeof(object))
grid[i]=calloc(ny,sizeof(double**))
would work, because size of pointer on pointer of double is the same as pointer of double, but it is not perfect.
if you have an array of int that you allocate like this:
int *array = calloc(ny,sizeof(int *))
it will work all right on most platforms, but if you are on a 64-bit architecture with a standard 32-bit int (windows 64-bit box for instance, gcc 64 bit compiler), since pointers are 64 bit, it will allocate twice as much memory as you really need. The correct syntax in that case is:
int *array = calloc(ny,sizeof(int))
because the element is an int, and it returns a pointer on int (int *)
So, now, recurrently, when you're adding a star on the left, you add a star on the right:
int **array = calloc(ny,sizeof(int *))
int ***array = calloc(ny,sizeof(int **))
and so on...
Small personal story: Some nasty crashes were encountered when migrating from 32-bit to 64-bit back in the days when people used to use:
int **array = calloc(ny,sizeof(int)) // WRONG!!
which worked while everything was 32-bit. When sizeof(int *) was increased to 8 bytes because of 64 bit arch, only half of the size was allocated, which could result in very funny bugs.
Related
In this code, while we are dynamically allocating memory for the 2D array, after 4 address why it is taking a gap of 16 bytes but when we are statically allocating 2D array then it does not have such gap.... what is the reason behind this???
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r = 3, c = 4, i, j, count;
int stat[r][c];
int *arr[r];
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
// Note that arr[i][j] is same as *(*(arr+i)+j)
count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count; // Or *(*(arr+i)+j) = ++count
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d\n", *(arr+i)+j);
printf("\n\n");
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d\n", *(stat+i)+j);
/* Code for further processing and free the
dynamically allocated memory */
return 0;
}
Because you are not allocating a 2D array. You are allocating a set of 1D arrays, and those allocations do not have to be contiguous (most malloc implementations reserve some bytes to store the size of the allocated block).
To dynamically allocate a "true" 2D array where number of rows and columns aren't known until runtime, you'd do something like this:
stat (*arr)[c] = malloc( sizeof *arr * r );
that would be contiguous like any "normal" 2D array.
But...
Strictly speaking, this behavior is undefined - since arr points to a VLA, the sizeof *arr expression must be evaluated at runtime, not at compile time, and arr is not a valid pointer value at that point. I've never seen this fail on any implementation I've used, but that doesn't mean it won't fail somewhere. If c were constant instead, like
stat (*arr)[3] = malloc( sizeof *arr * r );
then there wouldn't be a problem, and this would be the preferred way to dynamically allocate an Nx3 array.
If you need all array elements to be contiguous (such that you could traverse the entire array with a pointer or something like that), then the safest option is to allocate your memory as a 1D array:
stat *arr = malloc( sizeof *arr * r * c );
and compute the offsets manually:
x = arr[ i * r + j ];
If you want the convenience of 2D notation, you could try creating a pointer and setting to point to the beginning of the array, something like
stat (*ptr)[c] = (stat (*)[c]) arr;
but that kind of pointer aliasing is also undefined if the pointer types are not compatible, and we've no reason to expect that a pointer to T is compatible with a pointer to an array of T.
The comments on your question have the most essential advice - don't worry about where malloc puts your memory. There is no assurance that it will be in any order. It may locate allocations in pursuit of various optimizations or speculations, and may vary from one execution to the next. If nothing else, other memory allocations, calls to free, garbage collection (in languages with GC, that is) between your calls to malloc will affect the location of the next allocation.
This can also vary with compiler, compiler options, OS, etc.
As for the specific reason your allocations have a 16 byte gap, that's impossible to say without more, and likely very deep, insight into your scenario. BTW, you didn't include output of your printf in your question.
But if I had to guess, I'd say the memory manager was aligning the allocations up with memory boundaries...perhaps a 32-byte or 64-byte boundary.
You're allocating 4 * sizeof(int). If an int is 4 bytes on your system, that's 16 bytes. If your malloc likes to line things up to 32 bytes, that might explain the 16-byte gaps you're seeing.
But again...this is just a guess. The simple answer is...you shouldn't care.
But if you DO care for some reason, you probably need to do your own allocation. malloc a much larger chunk of memory, and then manage your own pointers and allocations internally.
I need to implemenet a simple dynamic array that can work with any type.
Right now my void** implementation is ~50% slower than using int* directly:
#define N 1000000000
// Takes ~6 seconds
void** a = malloc(sizeof(void*) * N);
for (int i =0; i < N; i++) {
*(int*)(&a[i]) = i;
}
printf("%d\n", *(int*)&a[N-1]);
// Takes ~3 seconds
int* b = malloc(sizeof(int) * N) ;
for (int i =0; i < N; i++) {
b[i] = i;
}
printf("%d\n", b[N-1]);
I'm not a C expert. Is there a better way to do this?
Thanks
edit
Look like using void** is a bad idea. Is there a way to implement this with void*?
Here's how it's implemented in Go:
type slice struct {
array unsafe.Pointer
len int
cap int
}
I'd like to do something similar.
edit2
I managed to implement this with void*.
The solution was really simple:
void* a = malloc(sizeof(int) * N);
for (int i = 0; i < N; i++) {
((int*)a)[i] = i;
}
printf("%d\n", ((int*)a)[N-1]);
Performance is the same now.
Your two alternatives programs are not analogous. In the second one, which is valid, you allocate space sufficient to hold N integers, and then assign values to the int-size members of that space. In the first one, however, you allocate space large enough to accommodate N pointers to void and then, without initializing those pointers, you try to assign values to the objects to which they point. Even if those pointers had been initialized to point to int objects, there is an extra level of indirection.
Your first code could be corrected, in a sense, like so:
void** a = malloc(sizeof(void*) * N);
for (int i =0; i < N; i++) {
a[i] = (void *) i;
}
printf("%d\n", (int) a[N-1]);
That relies on the fact that C allows conversions between pointer and integer types (although not necessarily without data loss), and note that there is only a single level of indirection (array indexing), not two.
Inasmuch as the behavior of your implementation of the first alternative is undefined, we can only speculate about why it runs slower in practice. If we assume a straightforward implementation, however, then such a performance penalty as you observe might arise from poor cache locality for all the array writes.
Be aware that sizeof(void *) is the double of sizeof(int) on 64 bits processors (8 bytes address versus 4 bytes signed integer). If that's your case, I bet the difference only is page cache miss. You memory unit is required to load two times more pages, which is slow (link for more information here).
Please also note that C++ vectors aren't "dynamic array that can work with any type". They are bound to a type, for instance: std::vector<int> is a dynamic array but where you can only store int.
A solution to your problem would be to implement some sort of std::vector<void *> in C. But it's not efficient:.
You need to do 2 allocations for each element (1 for the container and 1 for the element itself)
You need to do 2 levels of indirection each time you access the data (1 to get the pointer in the container and 1 to get the data in the element)
You need to store some kind of type information in each element. If not, you don't know what is in your dynamic array
I managed to implement this with void*.
The solution was really simple:
void* a = malloc(sizeof(int) * N);
for (int i =0;i<N;i++) {
((int*)a)[i] = i;
}
printf("%d\n", ((int*)a)[N-1]);
Performance is the same now.
I also came across this great article that explains how to implement a generic data structure in C:
http://jiten-thakkar.com/posts/writing-generic-stack-in-c
I am trying to develop the TicTacToe game in C and I am using the following structures.The myboard->a member is used to store 'X' or 'O' ,meaning the move a player has made in the same coordinates as the board , ie. 'X' in (1.1) or 'O' (3.1)
typedef struct{
int** a;
int size;
}_board;
typedef _board* board;
board myboard =(board) malloc(sizeof(board));
scanf_s("%d", &(myboard->size));
Size=is the size of the TicTacToe board nxn.
myboard->a =(int**)malloc(myboard->size*sizeof(char *));
if (myboard->a = NULL)
{
printf("ERROR!!!");
}
Until this point everything seems to work but when a try to allocate memory as you see bellow, a get a segmentation fault.
int i;
for (i = 0; j<myboard->size; i++)
{
myboard->a[i] = malloc(sizeof(char));
if (myboard->a[i] == NULL)
{
printf("ERROR");
}
}
I am using free for its malloc at the end of me program.
Thanks, in advance for any answer , and sorry for my bad english. Any help is apreciated.
I don't really understand why you are using a int** variable for storing your board data, when you could just use one simple int*, which you could later assign with malloc(3) as in:
int* b_data;
int b_size = 9;
b_data = malloc(b_size * sizeof(int));
// ... Your code
free(b_data);
If however, you really want to use a int** variable, you could do something like:
int** b_data;
int b_size_x = 3;
int b_size_y = 3;
int i;
b_data = malloc(b_size_x * sizeof(int*));
for(i = 0; i < b_size_x; i++)
*(b_data + i) = malloc(b_size_y * sizeof(int));
// ... Your code where you access your array of size_x containing
// arrays of size_y of int typed "cells"
for(i = 0; i < b_size_x; i++)
free(*(b_data + i));
free(b_data);
But this is really unnecessarily complicated, and I would dis-advise from doing so unless for learning purposes: in most cases, the allocated memory will be contiguous, so the second solution will allocate a nearly identical structure in memory, but will be less efficient (the "2D" array solution takes b_size_x times sizeof(int*) more memory), and the first solution will be simpler to read/write (so less prone to bugs, and easier to maintain).
Concerning your code, your problem is that myboard->a is NULL right after the "check" (which is in fact an allocation - note that the "ERROR" is never shown because myboard-> is then NULL, which evaluate to 'false'.):
if (myboard->a = NULL)
which should be:
if (myboard->a == NULL)
In addition, as pointed by #WhozCraig in his comment on your post, you might want to use i in the condition of your for loop, rather than j; and you also probably want to use int and int* types rather than char and char* types respectively in your malloc(s), since the a member of the board structure is an int**. Oh and also, think about putting newlines after your printf(3) strings, or use puts(3).
I am trying to track down a bug a big program. I think it is due to how I am passing arrays to my functions. Am I doing this correctly?
main(){
int *x = declarArray(x, 100);
int *y = declarArray(x, 100);
// lines of code....
x = arrayManip(x, 100);
// more code...
int i;
for(i=0; i<100; i++)
y[i] = x[i];
//more code...
free(x);
free(y);
}
This is how I manipulate arrays:
int *arrayManip(int *myarray, int length){
int i;
for(i=0; i<length; i++)
myarray[i] = i;
return array;
}
This is how I initialize the arrays:
int* declareArray(int *myarray, int length){
myarray = (int*) malloc(length*sizeof(int*));
if (myarray==NULL)
printf("Error allocating memory!\n");
int i;
for(i=0; i<length; i++)
myarray[i] = -888;
return myarray;
}
This code seems to work fine on a small scale, but maybe there is a problem once I have many more arrays of larger size that are often getting passed back and forth and copied in my program?
declarArray :
Name is not gramatically correct
The name of the function is not what it does
malloc with sizeof(int*), not sizeof(int). Guarantuee to be a bug in 64 bit machine
malloc fails, you print, but still write to null
passing myarray as argument is a noop as is
-888 is a magic number
There is no error check whatsoever
My advice. Throw it away and start fresh
No, as per my understanding.
You allocating one dim array => elements in that array should be integers and not pointers to integers so instead of this :
myarray = (int*) malloc(length*sizeof(int*));
it should be :
myarray = (int*) malloc(length*sizeof(int));
In function arrayManip you pass param named array, and than you trying to access it as myarray
This:
myarray = (int*) malloc(length*sizeof(int*));
allocates an array of length pointers to an integer, but then puts it into a pointer to an integer (i.e. an array of integers, not pointers to integers). If you want an array of integers, you want:
myarray = (int*) malloc(length*sizeof(int));
or (if you want to zero it):
myarray = (int*) calloc(length, sizeof(int));
which does the size x length calculation itself.
To allocate a list of pointers to integers, you want:
myarray = (int**) malloc(length*sizeof(int*));
or
myarray = (int**) calloc(length, sizeof(int*));
Unless you are fantastically concerned about speed, I find using calloc() results in fewer bugs from uninitialized arrays, and makes the reason for the allocated size more obvious.
The pointer is of word size [2 or 4 ,... depending on machine architecture]. whatever it may point to int,double,float,...
for integer pointer it works if it takes 4 bytes for int in machine. when u go for other data type it 'll lead you to error.
you should allot memory as
pointer = (DataType*) malloc (length * sizeof(DataType));
use malloc and to make your code clear.
void* malloc (size_t size);
malloc reference
use memset to allot default value [-888] for your array.
void *memset(void *str, int c, size_t n)
in the following snippet I wish the function accept a double pointer(2D array) which can be in any data type(in this case, integer), and use memcpy to copy one element at a time of the array to another variable. It passed the compiler but still shows an access violation.
I looked everywhere around the forum but still can't get this right.
Any tips are appreciated. I am nearly devastated by the complexity of C.
void ShowImg(void **ptr, IplImage *sample, char window_name[])
{
int value;
IplImage *sml_img= cvCreateImage(cvSize(sample->width,sample->height),IPL_DEPTH_8U, 1);
for(int j=0; j<sample->height; j++)
for(int i=0; i<sample->width; i++){
memcpy(&value, ptr+i*sizeof(int)+j*sample->width*sizeof(int), sizeof(int));
((uchar *)(sml_img->imageData + sml_img->widthStep*j))[i] = value;
printf("%d,%d\n", i, j);
}
cvNamedWindow(window_name);
cvShowImage(window_name, sml_img);
cvWaitKey(0);
cvDestroyWindow(window_name);
cvReleaseImage(&sml_img);
}
I think there's a mistake here: ptr+i*sizeof(int) since ptr is of type void** ptr+1 is the next element, meaning ptr+sizeof(void*), why would you multiply it by sizeof(int)?
for example:
ptr = 0x00000000,
sizeof(void*) = 4,
sizeof(int) = 4
||
\/
ptr+1 = 0x00000004.
ptr+1*sizeof(int) = 0x00000010.
and I don't think that's what you want. (the same about j*sample->width*sizeof(int))
memcpy(3) is really for copying objects that are larger than the primitive types. You could replace this line:
memcpy(&value, ptr+i*sizeof(int)+j*sample->width*sizeof(int), sizeof(int));
with this line:
value = ptr+i*sizeof(int)+j*sample->width*sizeof(int);
The sizeof(int) scaling is throwing me; you shouldn't need this if your datatypes are known to the compiler at compile time. Why is your array a void ** rather than something more specific, which the compiler could work with? (int ** would be a good first start, but I'm not very good at multidimensional arrays in C, so I'm not positive this would be a better replacement. But I do dislike what you have now. :)