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. :)
Related
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 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.
Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
See the following example
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt;
Serial.println(sizeof(testInt) / sizeof(int)); // returns 3
Serial.println(sizeof(point) / sizeof(int)); // returns 1
(This is a snipplet from Arduino Code - I'm sorry, I don't "speak" real C).
The easy answer is no, you cannot. You'll probably want to keep a variable in memory which stores the amount of items in the array.
And there's a not-so-easy answer. There's a way to determine the length of an array, but for that you would have to mark the end of the array with another element, such as -1. Then just loop through it and find this element. The position of this element is the length. However, this won't work with your current code.
Pick one of the above.
Also doing an Arduino project here...
Everybody on the internet seems to insist it's impossible to do this...
and yet the oldest trick in the book seems to work just fine with null terminated arrays...
example for char pointer:
int getSize(char* ch){
int tmp=0;
while (*ch) {
*ch++;
tmp++;
}return tmp;}
magic...
You can infer the length of an array if you have an array variable.
You cannot infer the length of an array if you have just a pointer to it.
You cannot and you should not attempt deduce array length using pointer arithmetic
if in C++ use vector class
You can if you point the the whole array and NOT point to the first element like:
int testInt[3];
int (*point)[3];
point = testInt;
printf( "number elements: %lu", (unsigned long)(sizeof*point/sizeof**point) );
printf( "whole array size: %lu", (unsigned long)(sizeof*point) );
Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
Technically yes, there is a way when code has a true pointer to an array as the array size is in the type as with int (*array_pointer)[3].
This differs from OP's code as the pointer point is not a pointer to an array, but a pointer to an int.
The line point = testInt; converts the array testInt to the address of the first element of the array (which is an int *) and assigns that to point. Thus the array size info is lost.
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt; // Get the address of testInt[0]
int (*array_pointer)[3] = &testInt; // Get the address of the array
printf("%zu\n", sizeof(testInt) / sizeof(int));
printf("%zu\n", sizeof(point) / sizeof(int));
printf("%zu\n", sizeof(*point) / sizeof(int));
printf("%zu\n", sizeof(*array_pointer) / sizeof(int));
printf("%p\n", (void *) testInt);
printf("%p\n", (void *) point);
printf("%p\n", (void *) array_pointer);
Sample output
3
2
1
3
0xffffcbc4
0xffffcbc4
0xffffcbc4
Pointers point and array_pointer both have values that point to the same location in memory, but the pointers differ in type.
With C99 or later that support variable length arrays, code could have been the below and achieved similar results without explicitly coding a 3 in the pointer definition.
int (*array_pointer_vla)[sizeof testInt/sizeof testInt[0]] = &testInt;
printf("%zu\n", sizeof(*array_pointer_vla) / sizeof(int));
Output
3
I see now see similarities to #user411313 answer. Perhaps the deeper explanation and VLA discussion will be useful.
Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
See the following example
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt;
Serial.println(sizeof(testInt) / sizeof(int)); // returns 3
Serial.println(sizeof(point) / sizeof(int)); // returns 1
(This is a snipplet from Arduino Code - I'm sorry, I don't "speak" real C).
The easy answer is no, you cannot. You'll probably want to keep a variable in memory which stores the amount of items in the array.
And there's a not-so-easy answer. There's a way to determine the length of an array, but for that you would have to mark the end of the array with another element, such as -1. Then just loop through it and find this element. The position of this element is the length. However, this won't work with your current code.
Pick one of the above.
Also doing an Arduino project here...
Everybody on the internet seems to insist it's impossible to do this...
and yet the oldest trick in the book seems to work just fine with null terminated arrays...
example for char pointer:
int getSize(char* ch){
int tmp=0;
while (*ch) {
*ch++;
tmp++;
}return tmp;}
magic...
You can infer the length of an array if you have an array variable.
You cannot infer the length of an array if you have just a pointer to it.
You cannot and you should not attempt deduce array length using pointer arithmetic
if in C++ use vector class
You can if you point the the whole array and NOT point to the first element like:
int testInt[3];
int (*point)[3];
point = testInt;
printf( "number elements: %lu", (unsigned long)(sizeof*point/sizeof**point) );
printf( "whole array size: %lu", (unsigned long)(sizeof*point) );
Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
Technically yes, there is a way when code has a true pointer to an array as the array size is in the type as with int (*array_pointer)[3].
This differs from OP's code as the pointer point is not a pointer to an array, but a pointer to an int.
The line point = testInt; converts the array testInt to the address of the first element of the array (which is an int *) and assigns that to point. Thus the array size info is lost.
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt; // Get the address of testInt[0]
int (*array_pointer)[3] = &testInt; // Get the address of the array
printf("%zu\n", sizeof(testInt) / sizeof(int));
printf("%zu\n", sizeof(point) / sizeof(int));
printf("%zu\n", sizeof(*point) / sizeof(int));
printf("%zu\n", sizeof(*array_pointer) / sizeof(int));
printf("%p\n", (void *) testInt);
printf("%p\n", (void *) point);
printf("%p\n", (void *) array_pointer);
Sample output
3
2
1
3
0xffffcbc4
0xffffcbc4
0xffffcbc4
Pointers point and array_pointer both have values that point to the same location in memory, but the pointers differ in type.
With C99 or later that support variable length arrays, code could have been the below and achieved similar results without explicitly coding a 3 in the pointer definition.
int (*array_pointer_vla)[sizeof testInt/sizeof testInt[0]] = &testInt;
printf("%zu\n", sizeof(*array_pointer_vla) / sizeof(int));
Output
3
I see now see similarities to #user411313 answer. Perhaps the deeper explanation and VLA discussion will be useful.
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.