In the hope of gaining a better understanding of the answers
given in this post, can someone please explain to me if the
following circular buffer implementation is possible, and if
not, why not.
#define CB_TYPE_CHAR 0
#define CB_TYPE_FLOAT 1
...
typedef struct CBUFF
{
uint16 total; /* Total number of array elements */
uint16 size; /* Size of each array element */
uint16 type; /* Array element type */
uint16 used; /* Number of array elements in use */
uint16 start; /* Array index of first unread element */
void *elements; /* Pointer to array of elements */
} CBUFF;
...
void cbRead(CBUFF *buffer, void *element)
{
if (buffer->type == CB_TYPE_CHAR)
{
/* The RHS of this statement is the problem */
*(char*)element = *(buffer->elements[buffer->start]);
}
/* Other cases will go here */
buffer->start = (buffer->start + 1) % buffer->total;
--buffer->used;
}
I understand that the LHS must be cast to char so that I can
dereference the void pointer. I also understand that this code
fragment:
buffer->elements[buffer->start]
gives the address of the 'buffer->start' element of the elements
array, which I also want to dereference in order to get to the
content of that address. Or at least that's what I take from
K&R.
Given all that, how do I tell the compiler that the content of
the memory at that address is a char, and that it is okay to
dereference it? There is something going on here I just don't
understand.
buffer->elements is also a void * so you need to cast it before you can do anything with it:
*(char*)element = ((char *)buffer->elements)[buffer->start];
Given all that, how do I tell the compiler that the content of the memory at that address is a char, and that it is okay to dereference it?
Well, you've already done it on the LHS of that line:
*(char*)element = *(buffer->elements[buffer->start]);
To derefence buffer->elements[n] you will need to cast that as well.
*(char*)element = *((char*)buffer->elements)[buffer->start];
Now the question is whether or not that cast is correct. I can't tell you that as you did not post the initialization of buffer->elements.
Related
I have N statically allocated structures.
struct exemple{
...
}
struct exemple array[N];
struct exemple *test_ptr = 0x3; /* random address */
Can I check if test_prt points to a valid address? i.e. it points to one "struct example" allocated.
You can't. You have to know. It's not a problem if you manage your pointers correctly. A good habit is to always set pointers to 0 / NULL as soon as you destroy the object they point to. Then you can just test with if (ptr) or if (!ptr) (or, more verbose: if (ptr == NULL) / if (ptr != NULL)).
Note that your last assignment
struct exemple *test_ptr = 0x3; /* random address */
is invalid. you can't assign an integer to a pointer. but you can cast it to the pointer type;
struct exemple *test_ptr = (struct exemple *)0x3; /* random address */
The result will depend on your implementation / system.
You can only check if pointer is valid by doing pointer != NULL because anything except `NULL' is treated by valid pointer.
In your case, to check if your pointer points to any of your array entry, you can only do this:
size_t i = 0;
int isValid = 0;
for (i = 0; i < N; i++) {
if (test_ptr == &array[i]) {
isValid = 1;
break;
}
}
if (isValid) {
//Pointer points to one of your array entry
}
But in general, you cannot just test if pointer points to specific valid location for you. It is up to you to take care of where it points. It can also have NON-NULL value but points to invalid location, for example:
int* ptr = malloc(10); //Now points to allocated memory
*ptr = 10;
free(ptr); //Free memory
*ptr = 10; //Undefined behaviour, it still points to the same address but
//we don't know what will happen. Depends on implementation
In general, no, you can't test if a pointer is valid or not.
But, if you want to know if a pointer points to an element of an array, you can:
if(test_ptr >= &array[0] && test_ptr < &array[N]
&& ((intptr_t)test_ptr - (intptr_t)array)%((intptr_t)(&array[1]) - (intptr_t)array) == 0) {
// test_ptr points to an element of array
}
This works because arrays are allocated contiguously.
There is no language method but in some circumstances you can try to have some known values at the certain points of the structure. If the pointed memory location has those values you can assume it as valid - but of course you do not have any guarantee. But you need to write your own functions when you create the structure, and when you destroy it (by filling with zeros before freeing the memory). It is a very week workaround - but if you connect with another measures and accept the overhead it makes the probability of the incorrect program behaviour lower.
Sometimes it is called a security cookie.
it is possible of course to make it more complicated - at certain positions you have only offsets to those cookies. It makes less probable that the random position in the memory will have such a chain of data :)
I don't know if I get your question properly.
If you want to know if a pointer points to a struct of some type (cast my structs to void * and vice-versa, for example), I do the next way:
#include <assert.h>
struct my_struct {
#ifndef NDEBUG
#define MY_STRUCT_MAGIC 0x1234abcd
uint64_t magic;
#endif
int my_data;
};
void init_struct(struct my_struct *s, int t_data) {
#ifdef MY_STRUCT_MAGIC
s->magic = MY_STRUCT_MAGIC;
#endif
s->my_data = t_data;
}
my_struct *my_struct_cast(void *vs) {
my_struct *s = vs;
#ifdef MY_STRUCT_MAGIC
assert(MY_STRUCT_MAGIC == s->magic);
#endif
return s;
}
It has a little bit more code because of inclusion of const-casting, but I think you get the idea.
If you want to know if test_ptr points to a aray member, you have to check this way: test_ptr >= array && test_ptr < &array[sizeof(array)/sizeof(array[0])]). If the pointer comes from void, char, or some kind of dangerout ariyhmetic, you could also check for test_ptr % sizeof(array[0])
If you want to know if a pointer points to valid memory "ever allocated" by your program, you will have to intercept allocs functions, save returned chunks pointer & size, and compute like the previous example.
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!)
I've looked at similar questions but haven't really found an answer to my problem.
In my program, I have a function, sortdata, as follows:
void sortdata(Person *arr[], int noElements)
{
/* temporary pointer to Person data type to aid with swapping */
Person *tempptr = (Person *)malloc(sizeof(Person));
int i = 0;
/* loop I am working on to sort my data */
if (arr[i]->zip > arr[i + 1]->zip)
{
/* stores value in index i for array inside of temporary pointer */
tempptr->name = arr[i]->name;
}
}
I'm receiving the error described in the question at this line:
tempptr->name = arr[i]->name;
temp is not recognized as a modifiable lvalue. Why is this? I have this code in another function within my program:
while ((gets(teststring)) != NULL && i < 50)
{
/* dynamically allocates memory for each index of the array */
arr[i] = (Person*)malloc(sizeof(Person));
/* takes in data from user/ input file */
strcpy(arr[i]->name, teststring);
gets(arr[i]->address);
gets(arr[i]->citystate);
gets(arr[i]->zip);
printf("\n");
}
I haven't previously initialized arr[] (arr[] is an array of pointers to a structure passed from elsewhere in the program).
How do I make it so that I can store the values in arr[i] within tempptr?
Here is my structure definition in case it is needed:
/* structure defintion with typedef */
typedef struct person{
char name[50];
char address[50];
char citystate[30];
char zip[10];
}Person;
This program is for a class assignment so while I appreciate any efforts to help, I am only concerned with how to be able to store values in tempptr so I can perform swaps. Thank you.
You need to use:
strcpy(tempptr->name, arr[i]->name);
You can't assign a char[50] array, you have to copy to it instead.
You need use strcpy to modify char[].
as a beginner in C, I am struggling with an obscure problem and because I couldn't find a solution to this particular problem I want to ask you the following:
Currently I am trying to understand void pointers and their arithmetic operations. I attempted to write a generic function, which accepts a void pointer to an array, the length of the array and size of one element and splits the given array into two different parts (list1 and list2):
void split(void *array, int arrlen, int objsize)
{
// divide the arrlen and save the values
int len_list1 = arrlen / 2;
int len_list2 = arrlen - len_list1;
// Allocate memory for two temporary lists
void *list1 = (void*)malloc(objsize * len_list1);
void *list2 = (void*)malloc(objsize * len_list2);
if (list1 == NULL || list2 == NULL)
{
printf("[ERROR]!\n");
exit(-1);
}
// list1 gets initialized properly with int and char elements
memmove(list1, array, len_list1*objsize);
printf("list1:");
print_arr(list1, len_list1);
// memmove((char*)list2, (char*)array+list_1_length, list_2_length*objsize); (*)
memmove(list2, (int*)array+len_list1, len_list2*objsize);
printf("list2:");
print_arr(list2, len_list2);
}
My problem is the following:
If I give this function an int array it will work fine, but if I call split() with a char array as an argument, I have to...
memmove((char*)list2, (char*)array+list_1_length, list_2_length*objsize);
//memmove((int*)list2, (char*)array+list_1_length, list_2_length*objsize);
comment line (*) out, in order to have the same results. A solution certainly could be to write an if-else condition and test the objsize:
if (objsize == sizeof(int))
// move memory as in the 1st code snippet
else
// move memory with the (int*) cast
But with this solution I would also have to check other data types, so it would be very kind of you to give me a hint.
Thanks!
-matzui
memmove(list2, (int*)array+len_list1, len_list2*objsize);
Here you typecast array to an int *, and add len_list1 to it. But adding something to a pointer, means it will be multiplied with the size of one element of the datatype of that pointer. So if an int is 4 bytes, and you add 5 to an int * variable, it will move 20 bytes.
Because you know exactly how many bytes you want to move the pointer, you can cast is to char * (char = 1 byte), and add the number of bytes to it.
So instead of (int*)array+len_list1, you can use (char*)array+(len_list1*objsize)
A void pointer is just a word-sized dereferencable pointer that implies no particular data type. Thus, you cannot do pointer math with it. To do what you're trying to do, declare an appropriately typed pointer in your function, and then set its value equal to that of the parameter void pointer.
I have a structure like this
struct quantum_reg_struct
{
int width; /* number of qubits in the qureg */
int size; /* number of non-zero vectors */
int hashw; /* width of the hash array */
COMPLEX_FLOAT *amplitude;
};
typedef struct quantum_reg_struct quantum_reg;
quantum_reg reg;
If *amplitude is pointing to the start of array of type COMPLEX_FLOAT then I want to be able to store this in a an array of type Complex_float. Is it possible for me?
Secondly I need to understand the usage of -> operator. What happens if something like this is written .
reg->amplitude[1] *= -1;
As is, your code would crash if you accessed amplitude without assigning it to point to memory.
quantum_reg reg;
reg.amplitude = malloc(5 * sizeof (COMPLEX_FLOAT));
reg.amplitude[0] = 1.2f; // I'm guessing COMPLEX_FLOAT is just a typedef'd float for this to work
reg.amplitude[1] = 1.5f;
// reg->amplitude won't compile because reg is not a pointer.
// if COMPLEX_FLOAT is a struct, then reg.amplitude->fieldname could work, where fieldname is something in COMPLEX_FLOAT.
free(reg.amplitude); // free the allocated memory.
If amplitude has a fixed number of elements, consider redefining it as an array, e.g. COMPLEX_FLOAT amplitude[5];. This is easier to use because you don't have to worry about malloc and free. The advantage of malloc and free is that you can pick the size (number of elements) at runtime, but if you don't need this, then stick with an array.
Yes you could doing something like this :
quantum_reg.amplitude = malloc(sizeof(*quantum_reg.amplitude) * n);
Now the -> operator is just a shortcut for
(*reg).amplitude