I have a function with a prototype like this:
ErrorType function(void ** parameter, other_args);
This function reads the pointer pointed by 'parameter' and changes it (think of it like a realloc).
Now, to be right according to the C Standard, if I want to pass the address of other pointer than a void *, I must declare a temporary void * variable and use that instead.
So that I want is to create a wrapper (I don't care if it's a function or a macro), that do the function call with any pointer type.
I think I could do that in C11 with _Generic and a function for each basic type, plus a function for all structs and a function for all unions, but I think it's too troublesome.
I also read about a GCC extension that let you to write statements and declarations in expressions, and I think that I can easily do that I want with that, but I prefer that my code compiles in all standard compilers, not only in GCC or Clang.
So the question is, is there any way to do that without too much problems in a C11 compiler?
If I understand the question correctly, you'd like for function to be able to modify various types of pointers. Well, there's bad news and good news about that.
Bad news: The object representation of pointers is opaque, so you'd need to communicate to your function which kind of pointer it should be working with, unless your function is guaranteed to copy an object representation from a source pointer's object representation and you know that the two representations have the same meaning.
For example, sizeof (double *) could be different than sizeof (void *)
Good news: A pointer to any object type can be cast to a void * and back again, which includes a void ** and a double ** any many other pointer-types. So you could have:
ErrorType function(void * ptr, int ptr_type, ...) {
void ** vpp;
double ** dpp;
...
...
switch (ptr_type) {
case PTR_TYPE_VOIDP:
vpp = ptr;
/* Now you can work with *vpp */
*vpp = ...
break;
case PTR_TYPE_DOUBLEP:
dpp = ptr;
/* Now you can work with *dpp */
*dpp = ...
break;
}
...
}
Related
I am always tempted to refer to void * as dynamic typing for C & C++, usually as a throwaway joke.
I could not find a wikipedia entry or a dictionary entry for Dynamic Type. Perhaps the term is non-sensical?
Questions:
Is void * a dynamic type?
Is QVariant a dynamic type?
Thanks.
Note this answer assumes dynamic type conversion as definition
void* is not a dynamic type, it is a pointer without a type, that doesn't make it a dynamic type because it's type does not automagically adapt to the situations as in Javascript.
For example such code wouldn't work at all:
void* test = malloc(20);
test[0] = 'E'; /* dereferencing void pointer */
puts(test);
Void pointers has to be casted by the programmer and in a sense that what would "dynamic" correspond to is not dynamic.
Some of C Compilers may cast void into other types automatically at compile time but that wouldn't make it dynamic.
Technically speaking similar thing can be done with char* too and you can convert it into a int and that wouldn't make it dynamic.
char* e = malloc(sizeof(int));
memset(e, 0, sizeof(int));
int coolint = *(int*)(e);
printf("%d", coolint);
It's better to think void* like an any type, anything stored in your computer's memory is represented by bytes and by themselves they do not correspond to any type they are just numbers make up the data.
Main usage area of void* in C is to emulate polymorphism.
I have a function that takes a string, an array of strings, and an array of pointers, and looks for the string in the array of strings, and returns the corresponding pointer from the array of pointers. Since I use this for several different things, the pointer array is declared as an array of (void *), and the caller should know what kind of pointers are actually there (and hence what kind of a pointer it gets back as the return value).
When I pass in an array of function pointers, however, I get a warning when I compile with -Wpedantic:
clang:
test.c:40:8: warning: assigning to 'voidfunc' (aka 'void (*)(void)') from 'void *' converts
between void pointer and function pointer [-Wpedantic]
gcc:
test.c:40:8: warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
fptr = find_ptr("quux", name_list, (void **)ptr_list,
Here's a test file, which despite the warning does correctly print "quux":
#include <stdio.h>
#include <string.h>
void foo(void)
{
puts("foo");
}
void bar(void)
{
puts("bar");
}
void quux(void)
{
puts("quux");
}
typedef void (* voidfunc)(void);
voidfunc ptr_list[] = {foo, bar, quux};
char *name_list[] = {"foo", "bar", "quux"};
void *find_ptr(char *name, char *names[], void *ptrs[], int length)
{
int i;
for (i = 0; i < length; i++) {
if (strcmp(name, names[i]) == 0) {
return ptrs[i];
}
}
return NULL;
}
int main() {
voidfunc fptr;
fptr = find_ptr("quux", name_list, (void **)ptr_list,
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();
return 0;
}
Is there any way to fix the warning, other than not compiling with -Wpedantic, or duplicating my find_ptr function, once for function pointers and once for non-function pointers? Is there a better way to achieve what I'm trying to do?
You can't fix the warning. In fact, in my opinion it should be a hard error since it's illegal to cast function pointers to other pointers because there are architectures out there today where this isn't just a violation of the C standard but an actual error that will make the code not work. Compilers allow it because many architectures get away with it even though those programs will crash badly on some other architectures. But it's not just a theoretical standard violation, it's something that causes real bugs.
For example on ia64 function pointers are (or at least used to be last time I looked) actually two values, both necessary to make function calls across shared libraries or a program and a shared library. Likewise, the common practice to cast and call function pointers to functions returning a value to a pointer to a function returning void because you know you'll ignore the return value anyway is also illegal on ia64 because that can lead to trap values leaking into registers causing crashes in some unrelated piece of code many instructions later.
Don't cast function pointers. Always have them match types. This is not just standards pedantry, it's an important best practice.
One solution is to add a level of indirection. This helps with lots of things. Instead of storing a pointer to a function, store a pointer to a struct storing a pointer to a function.
typedef struct
{
void (*ptr)(void);
} Func;
Func vf = { voidfunc };
ptrlist[123] = &vf;
etc.
This is something that has long been broken in the C standard and has never been fixed -- there is no generic pointer type that can be used for pointers to functions and pointers to data.
Before the C89 standard, all C compilers allowed converting between pointers of different types, and char * was generally used as a generic pointer that might point to any data type or any function. C89 added void *, but put in a clause that only object pointers could be converted to void *, without ever defining what an object is. The POSIX standard fixes this issue by mandating that void * and function pointers are safely convertable back and forth. So much code exists that converts function pointers to void * and expects it to work properly. As a result, pretty much all C compilers still allow it, and still generate the correct code, as any compiler that did not would be rejected as unusable.
Strictly speaking, if you want to have a generic pointer in C, you need to define a union that can hold either a void * or a void (*)() and use an explicit cast of the function pointer to the correct function pointer type before calling it.
The language lawyering reason is "because C standard does not explicitly allow it." C11 6.3.2.3p1/p8
1. 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.
8. A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall
compare equal to the original pointer. If a converted pointer is used
to call a function whose type is not compatible with the referenced
type, the behavior is undefined.
Notice that a function is not an object in C terminology, hence there is nothing that allows you to convert a pointer to a function to a pointer to void, hence the behaviour is undefined.
Castability to void * is a common extension though. C11 J.5 Common extensions 7:
J.5.7 Function pointer casts
1. A pointer to an object or to void may be cast to a pointer to a function, allowing data to be invoked as a function (6.5.4).
2. A pointer to a function may be cast to a pointer to an object or to void, allowing a function to be inspected or modified (for example, by a debugger) (6.5.4).
This is required by for example POSIX - POSIX has a function dlsym that returns void * but in fact it returns either a pointer to a function or a pointer to an object, depending of the type of the symbol resolved.
As to why this happens - nothing in C standard is undefined or unspecified if the implementations could agree on it. However there were and are platforms where the assumption that a void pointer and function pointer would be of the same width would really make things difficult. One of these is the 8086 16-bit real mode.
And what to use instead then? You can still cast any function pointer to another function pointer, so you can use a generic function pointer void (*)(void) everywhere. If you need both void * and a function pointer, you must use a struct or union or allocate void * to point to the function pointer, or ensure that your code only runs on platforms where J.5.7 is implemented ;)
void (*)() is recommended by some sources too, but right now it seems to trigger a warning in latest GCCs because it doesn't have a prototype.
With some modification you can avoid pointer conversations:
#include <stdio.h>
#include <string.h>
void foo(void)
{
puts("foo");
}
void bar(void)
{
puts("bar");
}
void quux(void)
{
puts("quux");
}
typedef void (* voidfunc)(void);
voidfunc ptr_list[] = {foo, bar, quux};
char *name_list[] = {"foo", "bar", "quux"};
voidfunc find_ptr(char *name, char *names[], voidfunc ptrs[], int length)
{
int i;
for (i = 0; i < length; i++) {
if (strcmp(name, names[i]) == 0) {
return ptrs[i];
}
}
return NULL;
}
int main() {
voidfunc fptr;
fptr = find_ptr("quux", name_list, ptr_list,
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();
return 0;
}
As pointed out in other answers you shouldn't be allowed to assign a function pointer to an object pointer such as a void*. But you can safely assign a function pointer to any function pointer. Use reinterpret_cast in C++.
Let me give an example:
typedef void(*pFun)(void);
double increase(double a){return a+1.0;}
pFun ptrToFunc = reinterpret_cast<void(*)(void)>(increase);
the plain
pFun ptrToFunc = increase;
doesn't compile on several compilers.
I'm answering this old question because it seems that one possible solution is missing from existing answers.
The reason why the compiler forbids the conversion is that sizeof(void(*)(void)) can be different than sizeof(void*). We can make the function more generic, so that it can handle entries of any size:
void *find_item(char *name, char *names[], void *items, int item_size, int item_count)
{
int i;
for (i = 0; i < item_count; i++) {
if (strcmp(name, names[i]) == 0) {
return (char*)items + i * item_size;
}
}
return NULL;
}
int main() {
voidfunc fptr;
fptr = *(voidfunc*)find_item("quux", name_list, ptr_list,
sizeof(ptr_list[0]),
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();
return 0;
}
Now the find_entry() function doesn't need to directly handle the item at all. Instead it just returns a pointer to the array, and the caller can cast it to a pointer-to-funcpointer before dereferencing it.
(The code snippet above assumes the definitions from original question. You can see full code also here: try it online!)
What are void type variable in C?
I have rough idea but not sure how i can use them for below scenario.
server/ client program
I have a struct array which contains hostname, address in server. I want to send it to the client over the socket. How i can achieve it?
struct ipinfo{
char hostname[64];
char address[64];
}
struct ipinfo allip[5];
I read some where that i can copy into specific memory location as void type variable and them send the variable? Can any one please explain this concept? I really appreciate it.
In C the only time void can be used as a variable type is if it's a pointer. They are handy for when you aren't sure what type of data you have coming.
void * somePointer;
This can be used for various things.
Referencing an object without knowing the type.
Handling plain memory without a type. Malloc (and I believe new in C++) returns a void pointer as at the moment the memory is without a type.
Try not to use void pointers though, they are generally a good idea to stay away from. Likely to cause errors and headaches. You can often times find a better solution.
The void keyword can also be used in front a function.
void printHello(void)
{
printf("Hello");
}
In this function we use void because it's not returning anything. Void functions can simply do whatever task we assign them without returning anything. We also don't need to pass any data into the function, so we specify void in the parameters.
Note: If you're ever learning C++, there's something you really need to keep in mind about function parameters.
void printHello() // <- This is bad in C, it will take any number of anything practically
{
printf("Hello");
}
Always put void in the parameters if you want no arguments passed in for C.
void printHello() // <- Good in C++, it won't allow any arguments on a call
{
std::cout << "Hello";
}
You cannot however use void as a variable type as in
void a = 0;
void b = 's';
void c = 5.5
// You can't use void to store anything
I don't think void means what you hope it means. void is used in C-like languages to indicate an unknown type, or no type. For example, void* is a void pointer. It's a memory address that has some data at it, but the format of the data (and even its size) is not specified. In order to use that data you need to assign some type to it, usually through an assignment or and explicit or implicit cast.
Here's an example:
void * memory = malloc(16);
memory[0] = 0; // this won't compile!
int * int_array = memory;
int_array[0] = 0; // this is ok because we know the type
void is also used to indicate that a function doesn't have a return value.
Here's an example:
void exit(int status);
void can also be used as an indication that you're intentionally discarding the return value of a function call. This can improve the readability of your program, or suppress some compiler diagnostics.
Here's an example:
(void)memset(memory, 0, 16); // why does memset have a return value??
Another use of void is to indicate an empty parameter list. In C, a function declared like main() has an unspecified parameter list, not an empty list.
Here's an example:
int main(void) {
...
}
I'm afraid that none of these application are likely to help you solve your socket problem.
void pointers are mainly used in function argument when you expect that argument to be of any type because you can cast any type to void then back to any type without loss of data , the only thing you can't do with a void pointer is to dereference it.
I have been working on some code that is similar to the following:
typedef struct
{
unsigned char x;
unsigned short y;
unsigned char[NUM_DEFINED_ELSEWHERE];
} My_Struct;
static My_Struct my_useful_struct; // Variables initialized elsewhere in code.
void myFunction(const My_Struct * p_my_struct)
{
/* Performs various read-only actions utilizing p_my_struct. */
}
void myOtherFunction(void)
{
static My_Struct * p_struct = &my_useful_struct;
myFunction(p_struct);
}
My code compiles without any problems, but when reviewed I was told that unless I typecast p_struct that this could lead to undefined behavior on certain platforms (i.e. 8051). However, I never even received a warning on the compiler. Is it true that not typecasting the pointer when passing it to the function with (const My_Struct *) could lead to undefined behavior?
The reason that I declared the above function with a pointer to const was because I wanted to be able to handle both a pointer to const and a pointer. Is it bad coding practice not to typecast in the above situation?
Thanks for your help!
This is absolutely fine; the compiler performs an implicit conversion from My_Struct * to const My_Struct *. §6.3.2.3 of the C99 spec says:
For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.
Furthermore, even if you declare the function with two inconsistent declarations, such that one file sees it declared like this:
void myFunction(My_Struct * p_my_struct);
even though it's actually defined like this:
void myFunction(const My_Struct * p_my_struct) { ... }
even that is allowed by the spec, even though the compiler doesn't know to perform an implicit conversion, because My_Struct * and const My_Struct * have the same representation (so the conversion is a no-op, anyway).
(Thanks to Christoph and awoodland for their comments clarifying the latter situation. In a previous version of this answer, I wrongly claimed that that would be undefined behavior.)
Edited to add: The reverse — defining a function with a declaration with a pointer-to-non-const parameter, but calling it using a declaration with a pointer-to-const parameter — is also allowed, for the same reason; but attempting to actually modify the data could well result in undefined behavior, depending on where it's from. (A char * can by initialized a string constant, for example, but it's undefined behavior to try to modify the data in that constant.)
Type casting constness onto or off of things is something I consider bad practice - there is generally nothing wrong with passing a non-const pointer into a function expecting a const one.
The exception is if there is some reason that the data can change part way through the execution (e.g. another thread touching the data pointed at) - then you might have a problem, but its not the sort of problem that typecasting will prevent. In this case you need to make your logic thread safe.
Don't forget that the const keyword can't be used by the compiler to guarantee constness either, although it can be used to detect problems where you think data should not change, but the compiler expects that you want to change it... its more of a documentation tool for you than anything else.
First I assume the & in the myFunction(&p_struct) call is a typo and what you really meant is myFunction(p_struct).
static My_Struct * p_struct = &my_useful_struct;
myFunction(p_struct);
When you pass p_struct there is absolutely no reason to cast the p_struct pointer in the function call. This is perfectly valid to pass a pointer to T in a function where the parameter is pointer to const T.
In the C Standard this is ruled by the constraints of the assignment operator (C99, 6.5.16.1p1). In a function call of a function declared with a prototype, the arguments are converted as if by assignment to the type of the corresponding parameters (C99, 6.5.2.2p7).
This works for me and I don't think the const pointer parameter yields undefined behavior, the compiler does an implicit conversion before calling the function:
typedef struct
{
unsigned char x;
unsigned short y;
unsigned char[NUM_DEFINED_ELSEWHERE];
} My_Struct;
static My_Struct my_useful_struct; // Variables initialized elsewhere in code.
void myFunction(const My_Struct * p_my_struct)
{
/* Performs various read-only actions utilizing p_my_struct. */
}
void myOtherFunction(void)
{
static My_Struct * p_struct = &my_useful_struct;
myFunction(p_struct);
}
I have a function pointer inside a struct that gets dynamically set at runtime to the address of another function in various places in my code. It is defined in my header file like this:
void *(*run)();
During compile time, I get the following warning about this:
warning: function declaration isn't a prototype
This warning is benign, because the pointer is used in many places in my code to call the function it points to, and everything works just fine. However, I would really like to silence the warning.
If I change it to this:
void *(*run)(void);
I get compile errors whever I use it, because the various functions that make use of the pointer have different numbers of arguments, and saying void inside the parenthesies tells the compiler it accepts no arguments.
I can't use a va_list or anything fancy like that, as this is simply a pointer to another function, and I use a single pointer for them all because it keeps the code clean and simple.
I can silence the warning with adding this to my compiler flags:
-Wno-strict-prototypes
But I'd rather not have to disable compiler warnings with flags if I can avoid it.
So my question is: How do I notate this function pointer in the code in such a way that the compiler is satisfied with the fact that it accepts any number of any kind of arguments?
The code works perfectly. I just want the warning to go away.
Store the pointer as a void * and cast to the appropriate function pointer type when necessary? Keep in mind that it isn't necessarily safe to call one type of function pointer as if it were another type, so the warning you're starting out with isn't entirely invalid.
You can cast a function pointer like so:
void *genericPointer = ...;
void (*fp)(int, int) = genericPointer;
fp(123, 456);
Note that:
There's no explicit casting necessary here, as void * can always be cast to any pointer type.
The initial "void" before (*fp) is the return type of the function pointer.
You are trying to do things clean - i.e. involve the compiler in checks, but the design you invented simply cannot be clean by its principle. You cannot involve compiler in prototype checks this way, because you always must know, which parameters to pass at this particular case in runtime. Compiler cannot check this and if you make a mistake, segmentation fault is on the way.
But if I remember well, something like this was maybe used also in linux kernel (?). The solution is to have a general pointer (like the one you have) and each time you call a particular function you just typecast it to the pointer to function with the particular arguments. You may need to typecast it to void * first to silence the compiler again :-)
In C, when you call a function without a prototype visible, default argument promotions are applied to all of the arguments that you pass to the function. This means that the types that you actually pass do not necessarily match the types received by the function.
E.g.
void (*g)();
void f()
{
float x = 0.5;
g(x); // double passed
}
This means that you need to know that the function that you are actually calling has a compatible signature to that implied by the arguments that you are passing after promotion.
Given that you need to know this in any case you must know the function signature of the actual function being called at the call site which is using the function pointer. With this knowledge it is usually simpler and cleaner to use a function pointer with the correct prototype and you can avoid default argument promotion entirely.
Note that as you are defining your functions with prototypes, when you assigned a pointer to your function to a function pointer without a prototype you effective converted, say, a void(*)(int, int) to a void(*)() so it is completely correct and desirable to perform the reverse conversion before calling the function. gcc allows both these conversions without emitting any warnings.
E.g.
void PerformCall( void(*p)() )
{
if (some_condition)
{
// due to extra knowledge I now know p takes two int arguments
// so use a function pointer with the correct prototype.
void(*prototyped_p)(int, int) = p;
prototyped_p( 3, 4 );
}
}
Try typedefing the function pointer declaration and then have the caller explicityly cast it:
typedef void *(*run)();
//when calling...
void my_foo() {}
run r = (run)my_foo;
If the different function signatures are known, use a union. Otherwise, use a pointer of type void (*)(void) (actually, any function pointer type would do) to hold the generic pointer and convert to the proper type when setting the value and calling the code.
Example using a union:
union run_fn
{
void *(*as_unary)(int);
void *(*as_binary)(int, int);
};
struct foo
{
union run_fn run;
};
void *bar(int, int);
struct foo foo;
foo.run.as_binary = bar;
void *baz = foo.run.as_binary(42, -1);
Example using explicit casts:
struct foo
{
void (*run)(void);
};
void *bar(int, int);
struct foo foo;
foo.run = (void *(*)(int, int))bar;
void *baz = ((void *(*)(int, int))foo.run)(42, -1);
Don't use a void * to hold function pointers - such a conversion is unspecified by the ISO C standard and may be unavailable on certain architectures.
Ignoring the warning and using your code as-is is actually also a possibility, but keep in mind that any function argument will be subject to the default argument promotions and it's your responsibility that the promoted arguments properly match the declared parameters.