ive seen functions passing pointers in their parameters and they are common in dynamic use executing different functions after afew steps. However i came across this representation in a header file:
void *allocate_mem(u_int32_t n);
Any clue to how it is to be used? Is the function a pointer or does it return a pointer?
See my comments.
Please use cdecl.org whenever you have questions like this... entering void *allocate_mem(u_int32_t), we get the following.
declare allocate_mem as function (u_int32_t) returning pointer to void.
So, we know allocate_mem returns void *. Now, you're probably wondering why you would ever want a pointer to void...
§6.3.2.3.1 of the C99 standard states as follows.
A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
Thus you can convert the result of allocate_mem to fit your needs, e.g.
float *data = allocate_mem(1024 * sizeof(float))
The function returns a pointer to the new memory allocated.
The return type is a void*, the reason being that the function doesn't know what you want to use it for.
If you want to use it as an array of integers, you would cast it to an int*
eg.
int *p = allocate_mem(4*10);
The argument is the size (bytes) of memory that needs to be allocated. Therefore, allocating 40 bytes for 4-byte integers makes an array of ten 4-byte integers.
A void * is a pointer to something. What it points to is not known, but the idea is for it to work as sort of a neutral pointer. A void* param can take any kind of pointer type. However great care needs to be taken while handling these pointers as they come with their own set of limitations. You cannot dereference a void* it has to be cast to a valid type. The same goes with applying pointer arithmetic.
Refer this discussion for more details - C - pointers in functions and void variable type?
Related
Inspired by comments to my answer here.
Is this sequence of steps legal in C standard (C11)?
Make an array of function pointers
Take a pointer to the first entry and cast that pointer to function pointer to void*
Perform pointer arithmetic on that void*
Cast it back to pointer to function pointer and dereference it.
Or equivalently as code:
void foo(void) { ... }
void bar(void) { ... }
typedef void (*voidfunc)(void);
voidfunc array[] = {foo, bar}; // Step 1
void *ptr1 = array; // Step 2
void *ptr2 = (char*)ptr1 + sizeof(voidfunc); // Step 3
voidfunc bar_ptr = *(voidfunc*)ptr2; // Step 4
I thought that this would be allowed, as the actual function pointers are only accessed through properly typed pointer. But Andrew Henle pointed out that this doesn't seem to be covered by Standard section 6.3.2.3: Pointers.
Your code is correct.
A pointer to a function is an object and you're casting a pointer to an object (a pointer to a function pointer) to void pointer and back again; and then finally dereferencing a pointer to an object.
As for the char pointer arithmetic, this is referred to by footnote 106 of C11:
106) Another way to approach pointer arithmetic is first to convert the pointer(s) to character pointer(s): In this scheme the integer expression added to or subtracted from the converted pointer is first multiplied by the size of the object originally pointed to, and the resulting pointer is converted back to the original type. For pointer subtraction, the result of the difference between the character pointers is similarly divided by the size of the object originally pointed to. When viewed in this way, an implementation need only provide one extra byte (which may overlap another object in the program) just after the end of the object in order to satisfy the ''one past the last element'' requirements.
Yes, the code is fine. There's various pitfalls and conversion rules at play here:
C splits all types in two main categories: objects and functions. A pointer to a function is a scalar type which in turn is an object. (C17 6.2.5)
void* is the generic pointer type for pointers to object type. Any pointer to object type may be converted to/from void*, implicitly. (C17 6.3.2.3 §1).
No such generic pointer type exists for pointers to function type. Thus a function pointer cannot be converted to a void* or vice versa. (C17 6.3.2.3 §1)
However, any function pointer type can be converted to another function pointer type and back, allowing us to use something like for example void(*)(void) as a generic function pointer type. As long as you don't call the function through the wrong function pointer type, it is fine. (C17 6.3.2.3 §8)
Function pointers point to functions, but they are objects in themselves, just like any pointer is. And so you can use a void* to point at the address of a function pointer.
Therefore, using a void* to point at a function pointer is fine. But not using it to point directly at a function. In case of void *ptr1 = array; the array decays into a pointer to the first element, a void (**)(void) (equivalent to voidfunc* in your example). You may point at such a pointer to function-pointer with a void*.
Furthermore, regarding pointer arithmetic:
No pointer arithmetic can be performed on a void*. (C17 6.3.2.2) Such arithmetic is a common non-standard extension that should be avoided. Instead, use a pointer to character type.
A pointer to character type may, as a special case, be used to iterate over any object (C17 6.2.3.3 §7). Apart from concerns regarding alignment, doing so is well-defined and does not violate "strict pointer aliasing", should you de-reference the character pointer (C17 6.5 §7).
Therefore, (char*)ptr1 + sizeof(voidfunc); is also fine. You then convert from void* to voidfunc*, to voidfunc which is the original function pointer type stored in the array.
As been noted in comments, you can improve readability of this code significantly by using a typedef to a function type:
typedef void (voidfunc)(void);
voidfunc* array[] = {&foo, &bar}; // Step 1
void* ptr1 = array; // Step 2
void* ptr2 = (char*)ptr1 + sizeof(voidfunc*); // Step 3
voidfunc* bar_ptr = *(voidfunc**)ptr2; // Step 4
Pointer arithmetic on void* is not in the C language. You re not doing it though, you are doing pointer arithmetic on char* which is perfectly OK. You could have used char* instead of void* to begin with.
Andrew Helne seems to be missing the fact that a pointer to a function is an object, and its type is an object type. It is a plain simple fact, not something veiled in a shroud of mystery as some other commentators seem to imply. So his objection to casting a pointer to a function pointer is unfounded, as pointers to any object type can be cast to void*.
However, the C standard doesn't seem to allow using (T*)((char*)p + sizeof(T)) in lieu of (p+1) (where p is a pointer to an element of an array of type T), or at least I cannot find such permission in the text. Your code might not be legal because of that.
Pointer always stores a integer value i.e address so why do we need to declare them with different data type.
Like
int a=3,*p=&a;
char c=r,*cha=&r;
why can't we do like
int *c;
char r=a;
c=&r;
Essentially it's because
Pointer arithmetic would not work if the pointer types were not explicit.
The pointer to member operator would not work for struct pointer types.
The alignment requirements for types can differ. It might be possible to store a char at a location where it's not possible to store an int.
The sizes of pointers are not guaranteed to be the same by the C standard: i.e. sizeof(int*) is not necessarily the same as sizeof(char*). This allows C to be used on exotic architectures.
To pass to the "user" of the pointer information about what kind of data the pointer points to. Basing on that it will/may depend how the pointed data will be interpreted and handled. Any time you can use a pointer to void, in this case that information is not available. Then, the user of that pointer should know from other sources what is pointed and how to work with it.
Batcheba has already 4 good reasons. Let me give some less important ones:
function pointer and data pointer are not even compatible according to the standard (Harvard architecture with separate code and data address spaces, memory models of segmented architectures, etc.).
the optimizer can exploit the fact that pointer on different types generally do not overlap and can elide a lot of memory loads that way (https://en.wikipedia.org/wiki/Pointer_aliasing)
int *c;
char r=a;
c=&a;
In your declaration a is just a character not a variable.
A pointer when defined can only store the address of a specific type of variable. If you declare c as int *c, the pointer can only point on variables of type integer.
Of course you can assign an address value to any type pointers.
int d;
char* cp = (char*)&d; // OK
float* fp = (float*)&d; // OK
But when you get content from the address, you MUST know the type. Otherwise the compiler will not know how to interpret it.
I have a question regarding the void pointer in c language. I would like to know Can we dereference a void pointer without knowing its type?
No, because you don't know how to interpret the data contained by the corresponding memory space. Memory itself has no type, and it is pointers that contains the type information. For example, memory pointed to by int * is interpreted as an int.
When dereferencing a void *, there is no way for the compiler to tell which type bytes starting from that address should be interpreted as. It can be a double, an unsigned long, or even an array of chars.
However, it is possible to get dereference a void * through casting, because the cast operator contains the information about object type.
No, A void pointer can be dereferenced only after explicit casting. For example:
int a = 5;
void *b = &a;
printf(“%d\n”, *((int*)b));
TL;DR No, you can't.
While dereferencing a pointer-to-type, you generate an "object" of the type.
Since a void is not a complete type, you cannot dereference a void* directly. That is why, you need to either
copy the pointer to another pointer of a complete type
cast the pointer to another complete type
and then, you can dereference to get the object of the new complete type.
You cannot. Dereferencing a void pointer requires an explicit cast beforehand.
You can ofcourse cast it to any particular type and then dereference it without knowing its original type, but why you would want to do that is beyond me.
Knowing more C++ than C I wondered if someone could explain the reason why malloc() always returns a pointer of type void, rather than malloc having been implemented with some mechanism which allows it to return a pointer of the type the user passed in? It just seems a little "hacky" constantly explicitly casting the returned void pointer to the type you want.
Well, in C you don't have to do the cast, so your point is moot. That is, these two statements are 100% equivalent:
char *x = malloc(100);
char *y = (char *)malloc(100);
Conversions to and from void * are implicit in C. So, to address your question, the very reason malloc returns void * is so that you don't have to cast.
Besides that, in C there's no way to pass type information around, so doing something like:
char *x = malloc(100, char);
is not possible.
If you're in C++, the cast is necessary, but you shouldn't be using malloc anyway - that's what new is for, and it does handle the type information correctly.
It's not hacky at all, from C standard ISO/IEC 9899 2011, section 6.2.2.3:
A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
So a pointer to void* is a valid pointer to whatever type you want without the need of explicit casting.
In addition to this you can't dynamically pass a type to a function to let so that it will return the correct type, you can pass just the size itself (so malloc would be able to allocate size_t count * size_t size but not return the correctly type in any case).
C has no mechanism for "passing a type" at all. Also, in C, conversion from void* to a pointer of any other type is automatic (no cast is needed) so malloc works naturally in C. It's only in C++ where malloc requires casts to work.
There are two reasons, first, malloc doesn't know why you need memory. So it just return number of bytes asked to return. Secondly you cannot de-reference void * easily so it can help you to avoid accidents.
int *p;
p = (int *)malloc(sizeof(int)*10);
I'm coding something in C and dealing with situations where it would be helpful to be able to say "cast this to a pointer pointing to a datatype with the same number of bytes as this number".
An example will make it clearer - I'm using size_t to get the size of a pointer on the system. Now I want to portably cast a void * pointer to a pointer to a datatype of that size. I know I could cast it to any pointer type and it would be the same length, but the pointer arithmetic differs depending on the datatype the variable is pointing to. Also, in my case size_t happens to be 8 bytes, and so does double, so I could just cast my void * to a double *, but I want a portable solution. Is there any way to do this?
What wrong about size_t* (assuming I understood your question)
In the general case, where you need pointer to a type with n bytes, you can do:
void *voidptr=... //assign whatever you want.
char (*myptr)[n]=voidptr; //a pointer to char[n]
If you want a pointer to a type that is the same size as a pointer, why not use void **?