C programming: casting a void pointer to an int? - c

Say I have a void* named ptr. How exactly should I go about using ptr to store an int? Is it enough to write
ptr = (void *)5;
If I want to save the number 5? Or do I have to malloc something to save it?

You're casting 5 to be a void pointer and assigning it to ptr.
Now ptr points at the memory address 0x5
If that actually is what you're trying to do .. well, yeah, that works. You ... probably don't want to do that.
When you say "store an int" I'm going to guess you mean you want to actually store the integer value 5 in the memory pointed to by the void*. As long as there was enough memory allocated ( sizeof(int) ) you could do so with casting ...
void *ptr = malloc(sizeof(int));
*((int*)ptr) = 5;
printf("%d\n",*((int*)ptr));

That will work on all platforms/environments where sizeof(void*) >= sizeof(int), which is probably most of them, but I think not all of them. You're not supposed to rely on it.
If you can you should use a union instead:
union {
void *ptr;
int i;
};
Then you can be sure there's space to fit either type of data and you don't need a cast. (Just don't try to dereference the pointer while its got non-pointer data in it.)
Alternatively, if the reason you're doing this is that you were using an int to store an address, you should instead use size_t intptr_t so that that's big enough to hold any pointer value on any platform.

A pointer always points to a memory address. So if you want to save a variable with pointer, what you wanna save in that pointer is the memory address of your variable.

Related

Why are pointer type casts necessary?

I cannot understand why are pointer type casts necessary, as long as pointers point to an address and their type is important only when it comes to pointer arithmetic.
That is to say, if I encounter the next code snippet:
int a = 5; then both
char*b = (char*)&a; and int*c = (int*)&a
point to the very same memory location.
Indeed, when executing char*b = (char*)&a part of the memory contents may be lost, but this is due to the type of b is char* which can store only sizeof(char) bytes of memory, and this could be done implicitly.
The pointer type is important when you dereference it, since it indicates how many bytes should be read or stored.
It's also important when you perform pointer arithmetic, since this is done in units of the size that the pointer points to.
The type of the pointer is most important when you dereference the pointer.
The excerpt
char *b = (int*)&a;
is wrong because int * cannot be assigned to char *. You meant char *b = (char *)&a;. The C standard says you need an explicit cast because the types are not compatible. This is the "yeah yeah, I know what I am doing".
The excerpt
int*c = (int*)&a;
is right, but &a is already a pointer to an int, so the cast will do no conversion, therefore you can write it as int *c = &a;.
as long as pointers point to an address and their type is important only when it comes to pointer arithmetic.
No, not only for pointer arithmetic. Its also important for accessing the data pointed by the pointer, the wrong way of accessing as in your example leads to improper results.
when executing charb = (int)&a part of the memory contents may be lost, but this is due to the type of b is char* which can store only sizeof(char) bytes of memory,
First of all, that is wrong to do (unless we really need to extract 1-byte out of 4-bytes)
Second, the application of pointer cast is mostly used w.r.t void*(void pointers) when passing data for a function which can handle many different type, best example is qsort

Malloc works without type cast before malloc C/C++ [duplicate]

This question already has answers here:
Do I cast the result of malloc?
(29 answers)
Closed 9 years ago.
I am learning about malloc function & I read this:
ptr= malloc(sizeof(int)*N)
Where N is the number of integers you want to create.
The only problem is what does ptr point at? The compiler needs to know what the pointer points at so that it can do pointer arithmetic correctly. In other words, the compiler can only interpret ptr++ or ptr=ptr+1 as an instruction to move on to the next integer if it knows that the ptr is a pointer to an integer.
This works as long as you define the variable ptr to be a pointer to the type of variable that you want to work with.
Unfortunately this raises the question of how malloc knows what the type of the pointer variable is - unfortunately it doesn't.
To solve this problem you can use a TYPE cast. This C play on words is a mechanism to force a value to a specific type. All you have to do is write the TYPE specifier in brackets before the value, i.e.:
ptr = (*int) malloc(sizeof(int)*N)
Questions
I have seen many places that they don't use (*int) before the malloc & even implementing a linked list with no errors. Why is that?
Why do pointers need to know anything except the size of memory they are pointing to?
Before you can use ptr, you have to declare it, and how you declare it is the pointer becomes.
malloc returns void * that is implicitly converted to any type.
So, if you have to declare it like
int *ptr;
ptr = malloc(sizeof(int)*N);
ptr will point to an integer array, and if you declare like
char *ptr;
ptr = malloc(sizeof(char)*N);
ptr will point to a char array, there is no need to cast.
It is advised not to cast a return value from malloc.
But I have seen many places that they don't use (*int) before the
malloc & even I made a linked list with this and had no errors. Why is
that?
Because they (and you also surely) declared the variable previously as a pointer which stores the return value from malloc.
why do pointers need to know anything except the size of memory they
are pointing to?
Because pointers are also used in pointer arithmetic, and that depends on the type it is pointed to.
Before allocating space for a pointer you need to declare the pointer
int *ptr;
Since return type of malloc is void *, it can be implicitly converted to any type. Hence
ptr= malloc(sizeof(int)*N);
will allocate space for N integers.
The only problem is what does ptr point at?
It points to a block of memory of size sizeof(int) * N.
The compiler needs to know what the pointer points at so that it can do pointer arithmetic correctly.
You are not doing any pointer arithmetic in your code, so this does not apply. Returning void * from malloc() is fine because void * can be implicitly converted to and from any object pointer type.
Also note that casting the return value to (int *) does not change the type of ptr itself. So it doesn't to any good. If ptr was of type void *, then you couldn't perform pointer arithmetic on it even if you wrote
void *ptr;
ptr = (int *)malloc(sizeof(int) * N);
How should I explain this better? A variable always has the same type, regardless of which type of value you assign to it (e. g. in this case, assigning a void * to an int * is fine because there's an implicit conversion.)
This is why you should not cast the return value of malloc(): it has no benefits. It doesn't help correctness, it can hide errors, and it decreases readability.
malloc returns pointer of type void and void type pointer is implicitly
converted to any type so if you don't use typecast then it will also work
int *ptr;
ptr=malloc(sizeof(int)*N)
but if you use malloc in c++ then you need to typecast.

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

Need assistance in understanding this code using malloc and pointers

Here is a little snippet of code from Wikipedia's article on malloc():
int *ptr;
ptr = malloc(10 * sizeof (*ptr)); // Without a cast
ptr = (int*)malloc(10 * sizeof (int)); // With a cast
I was wondering if someone could help me understand what is going on here. So, from what I know, it seems like this is what's happening:
1) initialize an integer pointer that points to NULL. It is a pointer so its size is 4-bytes. Dereferencing this pointer will return the value NULL.
2) Since C allows for this type of automatic casting, it is safe not to include a cast-to-int-pointer. I am having trouble deciphering what exactly is being fed into the malloc function though (and why). It seems like we are getting the size of the dereferenced value of ptr. But isn't this NULL? So the size of NULL is 0, right? And why are we multiplying by 10??
3) The last line is just the same thing as above, except that a cast is explicitly declared. (cast from void pointer to int pointer).
I'm assuming we're talking about C here. The answer is different for C++.
1) is entirely off. ptr is a pointer to an int, that's all. It's uninitialized, so it has no deterministic value. Dereferencing it is undefined behaviour -- you will most certainly not get 0 out! The pointer also will most likely not point to 0. The size of ptr is sizeof(ptr), or sizeof(int*); nothing else. (At best you know that this is no larger than sizeof(void*).)
2/3) In C, never cast the result of malloc: int * p = malloc(sizeof(int) * 10);. The code allocates enough memory for 10 integers, i.e. 10 times the size of a single integer; the return value of the call is a pointer to that memory.
The first line declares a pointer to an integer, but doesn't initialize it -- so it points at some random piece of memory, probably invalid. The size of ptr is whatever size pointers to int are, likely either 4 or 8 bytes. The size of what it points at, which you'd get by dereferencing it when it points somewhere valid, is whatever size an int has.
The second line allocates enough memory for 10 ints from the heap, then assigns it to ptr. No cast is used, but the void * returned by malloc() is automatically converted to whatever type of pointer is needed when assigned. The sizeof (*ptr) gives the size of the dereferenced ptr, i.e. the size of what ptr points to (an int). For sizeof, it doesn't matter whether ptr actually points to a valid memory, just what the type would be.
The third line is just like the second, but with two changes: It explicitly casts the void * return from malloc() to an int *, to match the type of ptr; and it uses sizeof with the type name int rather than an expression of that type, like *ptr. The explicit cast is not necessary, and some people strongly oppose its use, but in the end it comes down to preference.
After either of the malloc()s ptr should point to a valid location on the heap and can be dereferenced safely, as long as malloc was successful.
For line 2 malloc() is allocating enough memory to hold 10 pointers.
malloc() is a general purpose function void so it must be cast to whatever type you actually want to use, in the above example pointer to int.

Store pointer value

As I know, when a pointer is passed into a function, it becomes merely a copy of the real pointer. Now, I want the real pointer to be changed without having to return a pointer from a function. For example:
int *ptr;
void allocateMemory(int *pointer)
{
pointer = malloc(sizeof(int));
}
allocateMemory(ptr);
Another thing, which is, how can I allocate memory to 2 or more dimensional arrays? Not by subscript, but by pointer arithmetic. Is this:
int array[2][3];
array[2][1] = 10;
the same as:
int **array;
*(*(array+2)+1) = 10
Also, why do I have to pass in the memory address of a pointer to a function, not the actual pointer itself. For example:
int *a;
why not:
allocateMemory(*a)
but
allocateMemory(a)
I know I always have to do this, but I really don't understand why. Please explain to me.
The last thing is, in a pointer like this:
int *a;
Is a the address of the memory containing the actual value, or the memory address of the pointer? I always think a is the memory address of the actual value it is pointing, but I am not sure about this. By the way, when printing such pointer like this:
printf("Is this address of integer it is pointing to?%p\n",a);
printf("Is this address of the pointer itself?%p\n",&a);
I'll try to tackle these one at a time:
Now, I want the real pointer to be changed without having to return a pointer from a function.
You need to use one more layer of indirection:
int *ptr;
void allocateMemory(int **pointer)
{
*pointer = malloc(sizeof(int));
}
allocateMemory(&ptr);
Here is a good explanation from the comp.lang.c FAQ.
Another thing, which is, how can I allocate memory to 2 or more dimensional arrays?
One allocation for the first dimension, and then a loop of allocations for the other dimension:
int **x = malloc(sizeof(int *) * 2);
for (i = 0; i < 2; i++)
x[i] = malloc(sizeof(int) * 3);
Again, here is link to this exact question from the comp.lang.c FAQ.
Is this:
int array[2][3];
array[2][1] = 10;
the same as:
int **array;
*(*(array+2)+1) = 10
ABSOLUTELY NOT. Pointers and arrays are different. You can sometimes use them interchangeably, however. Check out these questions from the comp.lang.c FAQ.
Also, why do I have to pass in the memory address of a pointer to a function, not the actual pointer itself?
why not:
allocateMemory(*a)
It's two things - C doesn't have pass-by-reference, except where you implement it yourself by passing pointers, and in this case also because a isn't initialized yet - if you were to dereference it, you would cause undefined behaviour. This problem is a similar case to this one, found in the comp.lang.c FAQ.
int *a;
Is a the address of the memory containing the actual value, or the memory address of the pointer?
That question doesn't really make sense to me, but I'll try to explain. a (when correctly initialized - your example here is not) is an address (the pointer itself). *a is the object being pointed to - in this case that would be an int.
By the way, when printing such pointer like this:
printf("Is this address of integer it is pointing to?%p\n",a);
printf("Is this address of the pointer itself?%p\n",&a);
Correct in both cases.
To answer your first question, you need to pass a pointer to a pointer. (int**)
To answer your second question, you can use that syntax to access a location in an existing array.
However, a nested array (int[][]) is not the same as a pointer to a pointer (int**)
To answer your third question:
Writing a passes the value of the variable a, which is a memory address.
Writing *a passes the value pointed to by the variable, which is an actual value, not a memory address.
If the function takes a pointer, that means it wants an address, not a value.
Therefore, you need to pass a, not *a.
Had a been a pointer to a pointer (int**), you would pass *a, not **a.
Your first question:
you could pass a pointer's address:
void allocateMemory(int **pointer) {
*pointer = malloc(sizeof(int));
}
int *ptr;
allocateMemory(&ptr);
or you can return a pointer value:
int *allocateMemory() {
return malloc(sizeof(int));
}
int *ptr = mallocateMemory();
I think you're a little confused about what a pointer actually is.
A pointer is just variable whose value represents an address in memory. So when we say that int *p is pointer to an integer, that just means p is a variable that holds a number that is the memory address of an int.
If you want a function to allocate a buffer of integers and change the value in the variable p, that function needs to know where in memory p is stored. So you have to give it a pointer to p (i.e., the memory address of p), which itself is a pointer to an integer, so what the function needs is a pointer to a pointer to an integer (i.e., a memory address where the function should store a number, which in turn is the memory address of the integers the function allocated), so
void allocateIntBuffer(int **pp)
{
// by doing "*pp = whatever" you're telling the compiler to store
// "whatever" not in the pp variable but in the memory address that
// the pp variable is holding.
*pp = malloc(...);
}
// call it like
int *p;
allocateIntBuffer(&p);
I think the key to your questions is to understand that there is nothing special about pointer variables. A pointer is a variable like any other, only that the value stored in that variable is used to represent a position in memory.
Note that returning a pointer or forcing the caller to move the pointer in an out of a void * temp variable is the only way you can make use of the void * type to allow your function to work with different pointer types. char **, int **, etc. are not convertible to void **. As such, I would advise against what you're trying to do, and instead use the return value for functions that need to update a pointer, unless your function by design only works with a specific type. In particular, simple malloc wrappers that try to change the interface to pass pointer-to-pointer types are inherently broken.

Resources