C cast void * to type_t - c

I have following code from an object-oriented programming C book:
{
struct Set { int count; };
struct Set * set = malloc(sizeof(struct Set));
void * p = set;
const size_t size = * (const size_t *) p;
}
I cant understand how and why last line works. size_t size is dereferenced value of pointer of type size_t. pointer of type type_t is cast from void* p.
What is happening when I cast void* to type_t*, I could not find any information in the book or online tutorials. Can someone explain it to me or refer me to a good tutorial?

So what happens here is the following: You have a pointer to a structure (p) and you cast it to a const size_t * pointer, and use the value resulted. Supposedly the value should be the same as the value of p->count however do not really count on this. According to Can I trust sizeof(size_t) <= sizeof(unsigned long int) is always true? int and size_t must not have the same size, so you well might end up with accessing memory which is not yours.

Here, the void * p is being casted to const size_t * type and used as the initializer for the const size_t size variable. The value in the address [of type const size_t ]held by p is being used.

When you cast void* p to size_t* p you are telling the compiler that p is pointing to a value of type size_t
In fact p is pointing to a a Set structure, which happens to contain a single int. The code is assuming that the type size_t is the same size as int, which the standard seems to suggest it will be
However size_t is unsigned, so if the value in the int is negative it will not be read correctly. Currently the data in the Set structure is uninitialised, so the result will be random

Related

How to get struct address inside array of structs?

I'm trying to get struct's address.
I want to get address in an int *, and I want to change address by adding numbers to the int *. I tried several ways, but I can't solve it.
struct num_d {
unsigned char data;
unsigned char pad1;
unsigned char pad2;
unsigned char pad3;
};
struct num_d **m = malloc(sizeof(struct num_d *) * row);
for (int i = 0; i < row; i++)
{
m[i] = malloc(sizeof(struct num_d) * col);
}
How can I get m[0][0]'s address in an int *?
first things first lets typedef your struct, so we can type less and be more clear:
typedef struct num_d num_d;
void pointer
A pointer to void is a "generic" pointer type. A void * can be converted to any other pointer type without an explicit cast. we cannot de-reference a void * or do pointer arithmetic with it; you must convert it to a complete data type pointer first (like int* e.g.) then do the de-refrence or the pointer arithmetic.
Now, malloc() return a void* which points to the allocated heap buffer (if malloc successed in allocation other wise null is the return value).
you code become:
num_d** m = malloc(sizeof(num_d*) * row); /*m is an array of void* pointers (not initialized)*/
for (int i = 0; i < row; i++)
{
m[i] = malloc(sizeof(num_d) * col); /*in each element in m you have a void* that points to struct num_d on the heap*/
}
the sizeof(void*) is the same as sizeof any pointer (except function pointers in some machines/os).
putting it all together
How can I get m[0][0]'s address in an int *?
This is a wrong question! because m is an array of void* to "num_d structs" (holding the num_d heap address).
if you want the start address of the i-th num_d struct in the array m, then, just return the void* in the index i in this array m[i]. and if you want to cast it just cast it (no need actually) just assign it:
int* ptr = m[i];
Take in mind that compilers will warn you, regarding the assignment above (but this assignment is supported and legal) :
warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
or (no need again):
int* ptr = (int*)m[i];
I don't know why you need such behavior, it makes more sense to cast to num_d*
if you want the address of the first data member in the struct num_d, then you must cast to the appropriate data type to get the expected data:
unsigned char data = ((num_d*)m[i])->data;
unsigned char* p_data = &((num_d*)m[i])->data;
You don't need to have the address in an int* in order to be adding to it. The way that [] works, is that it adds to the pointer and dereferences.
You can just add to *(m[0] + 1) to get the second element.
How about:
int *ptr = (int *) m[0];

void * assignment to void **

Need to implement one api which has some parameters;which has input's type (const void*), output's type (void**); the api wants to assign input with some offset to the output; for example,
void getOffset(const void* a, void** b)
{
int offset = getsomeoffset();
*b = a + offset;
}
This will have some complain in the compiler. What's the correct way to write this code? The input's type can be float, int, double.
You cannot apply pointer arithmetics on a void * pointer. The target pointed to does not have any type and hence no size which could be used to calculate the offset.
Therefore you need to cast your pointer before applying the offset:
*b = ((char *)a) + offset;
With this statement the offset is interpreted as number of bytes.
The problem here is the offset. A void has no size, so C does not allow pointer arithmetics on void *. Assuming that you want to use byte addresses, you should pass through char * arithmetics:
void getOffset(const void* a, void** b)
{
int offset = getsomeoffset();
char *p = a; // automatic conversion from void * to char *
p += offset; // char pointer arithmetics
*b = p; // automatic conversion for char * to void *
// or directly: *b = ((char *) a) + offset;
}
Given void *a, a + offset violates 6.5.6 Additive operators, paragraph 8 of the C standard:
When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough...
A void * doesn't have a type, and it can't point to an actual object.
As others have noted, you have to cast the void * to another type, most likely char * would be appropriate.

Dynamically setting pointer to int giving incorrect size

I have a struct defined:
struct Query {
int *pages;
int currentpage;
};
struct Query *new = malloc(sizeof(struct Query));
new->pages = malloc(sizeof(int) * 4);
I then checked the size of new->pages to ensure that the size was 4 by doing:
int size = sizeof(new->pages)/sizeof(new->pages[0]);
However, size keeps returning 2 as opposed to 4.
Would anyone know what I might be doing wrong?
Thanks for your help.
Your expectation is wrong.
sizeof(new->pages) in
int size = sizeof(new->pages)/sizeof(new->pages[0]);
doesn't return the total number of int elements. Just the size of the int pointer (int*). Since sizeof(int*) is 8 and sizeof(int) is 4 on your platform, it returns 2.
By the way, you should use size_t for size as sizeof operator returns a size_t and %zu is the format specifier (in printf()) to print size_t.
You are seeing this because the sizeof operator yields the size of the type of its operand in bytes, and the type of new->pages is a pointer to integer, as defined by the struct, so it evaluates to the size of the pointer, rather than the array.
Note the difference by the example:
int arr[4] = {0,1,2,3};
int *p = arr;
printf("%zu\n", sizeof(arr)); // prints 16
printf("%zu\n", sizeof(p)); // prints 4
The convention of getting number of elements of an array using sizeof(arr)/sizeof(arr[0]) works ONLY on arrays, it does not work on pointers, you have to keep track the length on your own.
Pointer are not arrays.Despite the fact that the pointer can point to an array,applying the sizeof() operator on a pointer returns the size of pointer,not the size of the array that it points to.
So,in order to keep track of the size,i recommend that you use a variable of type size_t to store the value (size).
Oh yeah,and don't name any of your variables new in case you want to use a c++ compiler!
struct Query {
int *pages;
int currentpage;
};
size_t size = 4;
struct Query *p = malloc(sizeof(struct Query));
p->pages = malloc(sizeof(int) * size);

Assigning values to a void*

In C the fread() has a parameter of a void* which will be assigned the value of the next chunk of bytes being read from the file. My understanding is that a void* is used so that several data types can be given to the function. However when I try to use this type of parameter in my own function it seems that assigning a value to a void* is not allowed.
For example:
void* ptr = malloc(sizeof(int));
int n = 5;
*ptr = n; //Error here
This gives an error saying that void is not assignable. If this is the case then how does it work in the fread()?
The implementation of fread is none of your business, but presumably it will create a char-like pointer from your void pointer and assume that the pointer you provided was created from a valid, non-null object pointer. For example:
You:
int data[10];
fread(data, sizeof(int), 10, fp);
fread:
size_t fread(void * ptr, size_t sz, size_t nmemb, FILE * fp)
{
char * dst = ptr;
// read data into *dst in chunks of sz bytes
// ...
}
This makes sense because you can treat any object as an array of characters, but passing a void * argument is simpler since the conversions from object to void pointers are implicit and don't need explicit casts.
Maybe you need this: int* ptr = malloc(sizeof(int));, or recast it by *(int*)(ptr) = n.
fread() uses something like memcpy() to copy the data from a buffer that was filled using read() or _read() or READ() or something platform specific like that.
void by definition is not assignable.
You might do it this way:
*(int*)ptr = n;
But basically you (probably) make mistake in a way you allocate memory. i would recommend this:
int* ptr = malloc(sizeof(int));
int n = 5;
*ptr = n;

How to get an item from a void pointer to array when I know each element's size?

It comes when I want to write my own quicksort for educational purpose. This is what I got:
qsort(void* array, int count, int size, int(*compare)(const void*, const void*));
And I have size of each element in array, and pointer to the first element in array. How can I get each individual element in that array?
If size was generated with the sizeof operator, it is a multiple of sizeof(char) (which is 1 by definition). So cast the void* into a char*, and move size "characters" at a time.
(((char*)array) + i*size)
You would normally do the address arithmetic with char * pointers, e.g. to access element i of array:
char * array_ptr = (char *)array + i * size;
Easy enough, cast it to char* and do pointer arithmetic:
char *carray = (char*)array;
char *pointer_to_n = carray + n * size;
BTW, some compilers such as GCC have an extension that allows to do pointer arithmetic to void pointers as if they were pointers to char, but that is non portable.

Resources