converting a void * to an array - c

I need to convert an array an place it in a struct that has a void* element and back to another array:
unsigned short array[size];
//do something to the array
typedef struct ck{
void * arg1;
void * arg2;
void * arg3;
} argCookie;
argCookie myCookie;
myCookie.arg2=malloc(sizeof(array));//alloc the necessary space
memcpy(myCookie.arg2,&array,sizeof(array));//copy the entire array there
//later....
unsigned short otherArray[size];
otherArray=*((unsigned short**)aCookie.arg2);
It happens that this last line won't compile...
Why is that? obviously I've messed up somewhere...
Thank you.

You can't copy arrays by assigning it a pointer, arrays are not pointers, and you cannot assign to an array, you can only assign to elements of an array.
You can use memcpy() to copy into your array:
//use array, or &array[0] in memcpy,
//&array is the wrong intent (though it'll likely not matter in this case
memcpy(myCookie.arg2,array,sizeof(array));
//later....
unsigned short otherArray[size];
memcpy(otherArray, myCookie.arg2, size);
That assumes you know size , otherwise you need to place the size in one of your cookies as well.
Depending on what you need, you might not need to copy into otherArray, just use the data from the cookie directly:
unsigned short *tmp = aCookie.arg2;
//use `tmp` instead of otherArray.

You can't assign to arrays. Instead of
otherArray=*((unsigned short**)aCookie.arg2);
just use memcpy again, if you know the size:
memcpy(&otherArray, aCookie.arg2, size*sizeof(unsigned short));
If you don't know the size, you're out of luck.

unsigned short* otherArray = (unsigned short*)aCookie.arg2
Then you can use otherArray[n] to access the elements. Beware of an out-of-bound index.

Related

Why does this example of pointer dereferencing work?

I have some code, and it works, and I don't understand why. Here:
// This structure keeps the array and its bookkeeping details together.
typedef struct {
void** headOfArray;
size_t numberUsed;
size_t currentSize;
} GrowingArray;
// This function malloc()'s an empty array and returns a struct containing it and its bookkeeping details.
GrowingArray createGrowingArray(int startingSize) { ... }
// Self-explanatory
void appendToGrowingArray(GrowingArray* growingArray, void* itemToAppend) { ... }
// This function realloc()'s an array, causing it to double in size.
void growGrowingArray(GrowingArray* arrayToGrow) { ... }
int main(int argc, char* argv[]) {
GrowingArray testArray = createGrowingArray(5);
int* testInteger = (int*) malloc(1);
*testInteger = 4;
int* anotherInteger = (int*) malloc(1);
*anotherInteger = 6;
appendToGrowingArray(&testArray, &testInteger);
appendToGrowingArray(&testArray, &anotherInteger);
printf("%llx\n", **(int**)(testArray.headOfArray[1]));
return 0;
}
So far, everything works exactly as I intend. The part that confuses me is this line:
printf("%llx\n", **(int**)(testArray.headOfArray[1]));
By my understanding, the second argument to printf() doesn't make sense. I got to mostly by trial and error. It reads to me as though I'm saying that the second element of the array of pointers in the struct is a pointer to a pointer to an int. It's not. It's just a pointer to an int.
What does make sense to me is this:
*(int*)(testArray.headOfArray[1])
It's my understanding that the second element of the array of pointers contained in the struct will be fetched by the last parenthetical, and that I then cast it as a pointer to an integer and then dereference that pointer.
What's wrong with my understanding? How is the compiler interpreting this?
My best guess is that your appendToGrowingArray looks something like this:
void appendToGrowingArray(GrowingArray* growingArray, void* itemToAppend) {
growingArray->headOfArray[growingArray->numberUsed++] = itemToAppend;
}
though obviously with additional logic to actually grow the arrow. However the point is that the itemToAppend is stored in the array pointed to by headOfArray.
But, if you look at your appendToGrowingArray calls, you are passing the addresses of testInteger and anotherInteger -- these are already pointers to integers, so you are storing pointers to pointers to integers in your headOfArray when you really intend to store pointers to integers.
So, when you consider testArray.headOfArray[1], it's value is the address on main's stack of the variable anotherInteger. When you dereference it the first time, it now points to the address of the buffer returned by the second malloc call that you stored in anotherInteger. So, it's only when you deference it a second time that you get to the contents of that buffer, namely the number 6.
You probably want to write:
appendToGrowingArray(&testArray, testInteger);
appendToGrowingArray(&testArray, anotherInteger);
instead.
(As noted in a comment, you also should fix your mallocs; you need more than 1 byte to store an integer these days!)

Dynamic arrays of arrays

If I have:
typedef char pos[2]; /*btw I now know no one should do this*/
void someFunction(void) {
pos *s = malloc(sizeof(pos) * 2);
}
In the cases like this how s working? What is it? Arrays are like pointers except when you use sizeof on them you will get the "correct" size. So in this case the following means that s is going to be a pointing to a sizeof(char)*4 sized memory? But the type of s is a pointer to a pointer which means that you can't use s as a one dimensional array (or a pointer which points chars ) becouse you "still need to go through one level/layer of indirection/pointer". Or am I wrong?
How can I use s? As a 2 dimensional array or as a one dimensional one?
(If you are interested: I need this bc I want to return two pos from a function. Is there a better way? (despite fixing this and using a struct for storing position data instead of a 2-sized array))
This typedef costruct is just equivalent to:
#include <stdio.h>
void someFunction(void) {
char (*pos)[2];
pos = malloc(sizeof(*pos) * 2);
pos[0][0] = 1;
}
int main(void) {
someFunction();
return 0;
}
That means that pos is the pointer to two-elements array of char. You can use just like as two-dimensional array with fixed column size as two. Number of rows is controlled by malloc() call, in your case it happened to be two as well.

Handling an array of pointers

I'm attempting to create a struct that has an array of char pointers as one of its members and am having trouble attempting to set/access elements of the array. Each char pointer is going to point to a malloc'd buffer. This is the struct currently.
struct rt_args {
long threadId;
char (*buffers)[];
FILE* threadFP;
};
And when I attempt to access an element of buffers via
char *buffer = malloc(100);
struct rt_args (*rThreadArgs) = malloc( sizeof(long) +
(sizeof(char *) * (numThreads)) +
sizeof(FILE*)
);
rThreadArgs->buffers[0] = buffer;
I get the error "invalid use of array with unspecified bounds". I don't know what the size of the array is going to be beforehand, so I can't hardcode its size. (I've tried de-referencing buffers[0] and and adding a second index? I feel as though its a syntactical error I'm making)
You can't have arrays without a size, just like the error message says, at least not n the middle of structures. In your case you might think about pointers to pointers to char? Then you can use e.g. malloc for the initial array and realloc when needed.
Something like
char **buffers;
Then do
buffers = malloc(sizeof(buffers[0]) * number_of_pointers_needed);
Then you can use buffers like a "normal" array of pointers:
buffers[0] = malloc(length_of_string + 1);
strcpy(buffers[0], some_string);
char (*buffers)[SIZE];
declares buffers as a pointer to char array not the array of pointers. I think you need this
char *buffers[SIZE];
NOTE: Flexible array member can be used only when it is the last member of the structure.

passing element of dynamic multidimensional array to a function

I have code which already works but am trying to extend it.
unsigned char **data_ptr;
Allocate memory for the first "array"
data_ptr = (unsigned char **)malloc(sizeof(unsigned char **) * no_of_rows);
Then in a loop initialize each row
data_ptr[index] = (unsigned char *)malloc(sizeof(unsigned char*), rowsize));
I then pass the address of my array to a library function. It works fine if I just pass the start of a row...
LibFunction( info_ptr, &data_ptr[index] ) //OK
But I need to pass the address of where in a row I want the function to begin writing data.
These both compile but fail in operation
LibFunction( info_ptr,(unsigned char **)data_ptr[index] + 1);
or..
LibFunction( info_ptr,(unsigned char **)data_ptr[index][1]);
LibFunction is of the form
LibFunction(..., unsigned char **)
I'm allocating more memory than I need with rowsize so I don't think I'm overrunning the array. As I stated, the code works fine if I pass it the start of a row but bugs out if I
try to pass any other element. There may be something else wrong but I need to know first if my syntax is ok.
Can't find anything else on the net as regards passing the address of single element of dynamic 2d array.
LibFunction( info_ptr,(unsigned char **)data_ptr[index] + 1);
is wrong because data_ptr is an unsigned char **, so data_ptr[index] is an unsigned char *. Leave out the cast and correct the function you're calling, it should accept an unsigned char *.
Some corrections in your program, observed from the top few lines
Since,
unsigned char **data_ptr; // a pointer to a char pointer
get the sizeof(char*) and always avoid typecasting the pointer returned by malloc()
data_ptr = malloc(sizeof(unsigned char *) * no_of_rows);
And for doing the allocation for the rows,
data_ptr[index] = (unsigned char *)malloc(sizeof(unsigned char*)* rowsize));
To pass the address of where in a row you want the function to begin writing data, change the function signature as
LibFunction(..., unsigned char *)
It should be LibFunction(&data_ptr[row][start_here]), exactly the same as if it was just an unsigned char[ROWS][COLUMNS];.
In general, it is my experience that if you think you require casts in modern-day C, it is probable that you are muddled up with what you are trying to do. A nice read is a comment on a post by Linus Torvalds on /. on this kind of stuff.
You're not allocating room for no_of_rows pointers to pointers; there's an asterisk too many in there. Also, you really [shouldn't cast the return value of malloc(), in C][1].
Your first allocation should be:
data_ptr = malloc(no_of_rows * sizeof *data_ptr);
But I need to pass the address of where in a row I want the function to begin writing data
So let's start simple, to make an array the correct size, forget trying to get the sizeof a complex type, we can simply do this:
unsigned char **data_ptr;
data_ptr = malloc(sizeof(data_ptr) * no_of_rows); //Just sizeof your var
Now you've got the correct memory malloc'd next you can malloc the memory for the rest easily:
for(index = 0; index < no_of_rows; index++)
data_ptr[index] = malloc(sizeof(unsigned char*) * rowsize);
Last point, now that we've got all that set up, you should initialize your array:
for(index = 0; index < no_of_rows; index++)
for(index2 = 0; index2 < rowsize; index2++)
data_ptr[index][index2] = 0;
As for your function, you want it to take a "portion" of an array, so we need it to take an array and a size (the length of the array to initialize):
void LibFunction(unsigned char data[], int size);
Then we're your ready to store some data it's as easy as:
LibFunction(&data_ptr[1][2], 3); // store data in second row, 3rd column, store
// three values.
You can do something like this:
unsigned char* ptr = &data[0][1];
LibFunction(info_ptr, &ptr);

pointer to an array boundary problem

I am programming in C. I am using also a library to create tasks which can communicate among them via messages. The content of these messages must be the pointer to the data you want to exchange.
In my case I want to send an array so I am sending a pointer to the array. In the receiving task I can then access the different elements by increasing the pointer, but, is there a way to know how long the array was?
Thank you in advance.
No, there is no way to do this as arrays decay to pointers when passed to functions, thus all information regarding size is lost.
You can include another parameter to specify the array length
void func(int len, int arr[]);
You can mark the end of the array with a special value (perhaps like argv does)
You can put your array into a structure and pass that (and suffer the performance penalties) or pass the a pointer to the structure
struct args {
int arr[100];
};
If you decide to go the first route, you can use a nice feature of C99, even if it doesn't actually enforce that arr has at least len elements:
void func(int len, int arr[len]);
No. So consider something slightly different.
struct arrayinfo {
struct element *array;
int count;
};
Then you can pass a pointer to your struct arrayinfo type and your receiving task will know how many elements are in your array.
An alternative technique is to make your array and array of pointers. Make your array one element bigger than necessary and set the last element to NULL.
No, you can't. The compiler doesn't know what the pointer is pointing to. You either need to pass the length value along with the array or you can trick it by allocating extra memory in order to store the length value before the start of the array.
No, that is not possible unless you also send the size of the array or set a guardian value in the end of the array.
I suggest that you do not send the array directly but use a intermediary struct, like the following:
struct intermediary {
int *the_array; /* the pointer to the array */
size_t size; /* the array size */
};
In the message you send the struct, and not the array itself.
Couldn't you use some kind of sentry value at the end of the buffers where the messages are stored. That should be such a value that you won't find it anywhere in the message. Depending on the type of these message its possible that there is such a value: typically a negative number if your messages consists of positive integers, a "INF" or "BIG_INT" number, etc. Then, you must process your message just up to the sentry value. Something like this:
#include <stdlib.h>
#include <string.h>
#define N 100
#define ENDTAG -999999
void foo( int *arr ){
int i = 0;
while( arr[i] != ENDTAG ){
//do whatever
i++;
}
}
int main( void ){
int *arr = (int *) malloc( sizeof(int) * N );
//fill the array, no matter how.
// ...
//set the sentry value
arr[N-1] = ENDTAG;
foo( arr );
free( arr );
return 0;
}
It may sound to much simple, but I actually used something like that more than once. You must though be absolutely sure that you'll take some restricted types of messages.

Resources