Explanation of converting from void* to int in c - c

in my code i have:
int number_compare(void *val1, void *val2) {
if (*(int*) val1 < *(int*s) val2) {
So basically to convert from void* to int i have to cast *(int *).
This works and give me the correct results, could someone please tell me why though or point me to a thread that explains it. I have already looked and cannot find an answer I understand.

That's not converting a void * to an int. It's interpreting whatever the void * is pointing at as an int. Break it down:
val1 // void pointer - not dereferenceable
(int *)val1 // pointer to 'int'
*(int *)val1 // the 'int' being pointed to
So your function is getting passed two pointers: it then interprets them as pointers to int and dereferences them, comparing the two int values being pointed to.
In contrast, converting from a void * to an int would look something like this:
int x = (int)val1;
But that's almost certainly not what you want - first because int is signed, and pointers aren't, and second because int and pointer types might not be the same size.

first thing void pointer cannot be defreferenced. maybe because it doesn't yet know how to fetch data. (i.e) if its char should fetch 1 byte, int 4 bytes...
so here first you are converting some address (void pointer) to int pointer.
(int*) val1;
later to fetch the value from that address [now the system knows it should take data from 4 bytes from that address : val1].
*(int*)val1
this 'll give you the data in that address.
This is formally said to be casting "(data_type) data" casting the data to specified data_type;

Related

Casting char** to char* - Does it change what it points to?

If I have a pointer to an array of char*s, in other words, a char** named p1, what would I get if I do (char*)p1? I’m guessing there would be some loss of precision. What information would I lose, and what would p1 now be pointing to? Thanks!
If you had asked about converting an int ** to an int *, the answer would be different. Let’s consider that first, because I suspect it is more representative of the question you intended to ask, and the char * case is more complicated because there is a special purpose involved in that.
Suppose you have several int: int a, b, c, d;. You can make an array of pointers to them: int *p[] = { &a, &b, &c, &d };. You can also make a pointer to one of these pointers: int **q = &p[1];. Now q points to p[1], which contains the address of b.
When you write *q, the compiler knows q points to a pointer to an int, so it knows *q points to an int. If you write **q, the compiler, knowing that *q points to an int, will get *q from memory and use that as an address to get an int.
What happens if you convert q to an int * and try to use it, as in printf("%d\n", * (int *) q);? When you convert q to an int * you are (falsely) telling the compiler to treat it as a pointer to an int. Then, * (int *) q tells the compiler to go to that address and get an int.
This is invalid code—its behavior is not defined by the C standard. Specifically, it violates C 2018 6.5 7, which says that an object shall be accessed only by an lvalue expression that has a correct type—either a type compatible with that of the actual object or certain other cases, none of which apply here. At the place q points, there is a pointer to an int, but you tried to access it as if it were an int, and that is not allowed.
Now let’s consider the char ** to char * case. As before, you might take some char **q and convert it to char *. Now, you are telling the compiler to go to the place q points, where there is a pointer to a char, and to access that memory location as if there were a char there.
C has special rules for this case. You are allowed to examine the bytes that make up objects by accessing them through a char *. So, if you convert a char ** to char * and use it, as in * (char *) q, the result will be the first (lowest addressed) byte that makes up the pointer there. You can even look at the rest of the bytes, using code like this:
char *t = (char *) q;
printf("%d\n", t[0]);
printf("%d\n", t[1]);
printf("%d\n", t[2]);
printf("%d\n", t[3]);
This code will show you the decimal values for the first four bytes that make up the pointer to char that is at the location specified by q.
In summary, converting a char ** to char * will allow you to examine the bytes that represent a char *. However, in general, you should not convert pointers of one indirection level to pointers of another indirection level.
I find pointers make much more sense when I think of them as memory addresses rather than some abstract high level thing.
So a char** is a memory address which points to, a memory address which points to, a character.
0x0020 -> 0x0010 -> 0x0041 'A'
When you cast you change the interpretation of the data, not the actual data. So the char* is
0x0020 -> 0x0010 (unprintable)
This is almost certainly not useful. Interpreting this random data as a null terminated string would be potentially disastrous.

what does it mean to have a void* member of a struct in c?

I don't understand what kind of property the mystery member is below:
typedef struct _myobject
{
long number;
void *mystery;
} t_myobject;
What kind of member is this void member? How much memory does that take up? Where can I get more information about what that accomplishes (for instance, why would one use a void member?)
EDIT-- updated title to say void*
A void* variable is a "generic" pointer to an address in memory.
The field mystery itself consumes sizeof(void*) bytes in memory, which is typically either 4 or 8, depending on your system (on the size of your virtual memory address space, to be more accurate). However, it may point to some other object which consumes a different amount of memory.
A few usage examples:
int var;
char arr[10];
t_myobject obj;
obj.mystery = &var;
obj.mystery = arr;
obj.mystery = malloc(100);
Your struct declaration says void *, and your question says void. A void pointer member is a pointer to any kind of data, which is cast to the correct pointer type according to conditions known at run-time.
A void member is an "incomplete type" error.
Variable of type void * can hold address of any symbol. Assignment to this variable can be done directly but while dereferencing it needs to be type cast to the actual type. This is required to inform the compiler about how much memory bytes needs to be accessed while dereferencing. Data type is the one which tells the size of a variable.
int a = 10;
char b = 'c';
void *c = NULL;
c = &a;
printf("int is %d\n", *((int*)c));
c = &b;
printf("char is %c\n", *(char*)c));
In above example void pointer variable c stores address of int variable a at first. So while dereferencing void pointer c, its typecasted to int *. This informs the compiler to access 4 byte (size of int) to get the value. And then in second printf its typecasted to char *, this is to inform the compiler to access one byte (size of char) to get the value.
Wrong question header. The member is 'void *', not 'void'.
A pointer to anything, rather than nothing.

Void pointers pretending to be void double pointers

I've been doing some thinking. I haven't found anything directly answering this question, but I think I know the answer; I just want some input from some more experienced persons.
Knowns:
A void pointer points to just a memory address. It includes no type information.
An int pointer points to a memory address containing an int. It will read whatever is in the memory address pointed to as an integer, regardless of what was stuffed into the address originally.
Question:
If a void double pointer void ** foo were to point to a dynamically allocated array of void pointers
void ** foo = malloc(sizeof(void *) * NUM_ELEMENTS);
is it true, as I am supposing, that because of the unique nature of void pointers actually lacking any sort of type information that instead of void ** foo an equivalent statement would be
void * bar = malloc(sizeof(void *) * NUM_ELEMENTS);
and that when I use indirection to access by assigning a specific type, such as with
(It was pointed out that I can't dereference void pointers. For clarity to the purpose of the question the next line is changed to be appropriate to that information)
int ** fubar = bar;
that I would get an appropriate pointer from the single void pointer which is just acting like a double pointer?
Or is this all just in my head?
It is permissible to assign the result of malloc to a void * object and then later assign it to an int ** object. This is because the return value of malloc has type void * anyway, and it is guaranteed to be suitable for assignment a pointer to any type of object with a fundamental alignment requirement.
However, this code:
#define NUM_ELEMENTS 1000
void *bar = malloc(sizeof(void *) * NUM_ELEMENTS);
int **fubar = bar;
*fubar = 0;
is not guaranteed by the C standard to work; it may have undefined behavior. The reason for this is not obvious. The C standard does not require different types of pointers to have the same size. A C implementation may set the size of an int * to one million bytes and the size of a void * to four bytes. In this case, the space allocated for 1000 void * would not be enough to hold one int *, so the assignment to *fubar has undefined behavior. Generally, one would implement C in such a way only to prove a point. However, similar errors are possible on a smaller scale: There are C implementations in which pointers of different types have different sizes.
A pointer to an object type may be converted to a pointer to another object type provided the pointer has alignment suitable for the destination type. If it does, then converting it back yields a pointer with the original value. Thus, you may convert pointers to void * to pointers to void and back, and you may convert pointers to void * to pointers to int * and back, provided the alignments are suitable (which they will be if the pointers were returned by malloc and you are not using custom objects with extended alignments).
In general, you cannot write using a pointer to an object type and then read the same bytes using a pointer to a different object type. This violates aliasing rules. An exception is that if one of the pointers is to a character type. Also, many C implementations do support such aliasing, but it may require setting command-line options to enable such support.
This prohibition on aliasing includes reinterpreting pointers. Consider this code:
int a;
int *b = &a;
void **c = (void **) &b;
void *d = *c;
int *e = (int *) d;
In the fourth line, c points to the bytes that b occupies but *c tries to interpret those bytes as a void *. This is not guaranteed to work, so the value that d gets is not necessarily a pointer to a, even when it is converted to int * as in the last line.
Under the C Standard, the behavior of the code you gave is undefined because you allocated an array of void pointers and then tried to use it as an array of int pointers. There is nothing in the Standard that requires these two kinds of pointer to have the same size or alignment. Now if you had said
void * bar = malloc(sizeof(int*) * NUM_ELEMENTS);
int ** fubar = bar;
Then all would be fine.
Now on the vast majority of machines, an int* and a void* will actually have the same size and alignment. So your code ought to work fine in practice.
Additionally, these two are not equivalent:
void ** foo = malloc(sizeof(void *) * NUM_ELEMENTS);
void * bar = malloc(sizeof(void *) * NUM_ELEMENTS);
This is because foo can be dereferenced at any element to get a void pointer, while bar cannot. For example, this program is correct and prints 00000000 on my 32-bit machine:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void **a = calloc(10, sizeof(void*));
printf("%p\n", a[0]);
return 0;
}
One other point is that you seem to be thinking that type information is explicit in the pointer at the machine level. This is not true (at least for the vast majority of implementations). The type of C pointers is normally represented only while the program is being compiled. By the time compilation is done, explicit type information is normally lost except in debugging symbol tables, which are not runnable code. (There are some minor exceptions to this. And for C++ the situation is very different.)

dereference an array of void pointers

I have a set of void pointers which I would like to put in an array of void pointers. I start with malloc:
void **p2vals=malloc(nelems*sizeof(void*));
..which gives me an array of pointers to pointers. But then I want to dereference p2vals like *p2vals which supposedly gets me one void pointer. Of course the compiler doesn't like it but I have a need for it. I want to set
*(p2vals+someoffset)=somevoidptr;
If you want to store memory address as a variable, I suggest you to use uintptr_t instead of void *.And if you want write or read any offset, just do (uintptr_t)((char *)(pointer) + offset).
Consider,
int a = 5;
int *p = &a;
In this case we indicate to the compiler that p is going to point to an integer. So it is known that when we do something like *p , at runtime, the no. of bytes equal to size of an int would be read.
Dereferencing void pointers, the compiler will not understand how many bytes to read exactly. You need to typecast them to some type before
using them

Finding end of char pointer, int and float

I have a function that will be passed a void pointer. This pointer can either be an int, char, or float. I know what data type will be passed to me by means of an associated value. For example, below is what my function looks like:
void * (int type, void * data);
If the void pointer I am passed was originally a char type, and I cast it back to a char type, is there a way of determining how many bytes are associated with that pointer? For example, if my function is called as follows:
f(1, (void *)"Hello world");
and I cast the void pointer back to a char pointer
char * p = (char *)data;
Is there some way I can figure out how many bytes were used? Would I possibly have to search for the null character and count how many bytes away it is from the original pointer? What would I have to do to find the size of the int and float as well?
Would I possibly have to search for the null character and count how
many bytes away it is from the original pointer?
Yes, if your void* is actually a char* this will work.
What would I have to do to find the size of the int and float as well?
int and float as always the same size (it depends from your architecture, generally 32 or 64 bit. Use sizeof operator to determine the exact size). If you are passing an array of int as void* you haven't any way to find its length.
Generally in these cases it's convinent to pass the size to your function too.

Resources