test.c
int main () {
void a;
return 0;
}
I use gcc to compile but it gives me an error:
error: variable or field 'a' declared void
From what I read here,
I thought I can declare void variable without problem.
As your link states:
A variable that is itself declared void (such as my_variable above) is useless; it cannot be assigned a value, cannot be cast to another type, in fact, cannot be used in any way.
This means that although syntactically correct, a void declaration is not useful to anything, this is why GCC could consider it an error. Even if it would compile, you won't be able to do anything with the variable, so I guess your question is just related to testing this behavior.
In fact void is useful just when we're talking about pointers (void*) since it allows you to declare a generic pointer without specifying the type.
No, but you can declare a void pointer: void *. A void * can hold any object pointer.
void *'s are only guaranteed to hold object (i.e. data) pointers
[but]
it is not portable to convert a function pointer to type void *
Although the book states that void a; is a valid statement, I don't believe it has ever been standards compliant. That being said, the first edition of the book was from 1987, so it could also be carry-over from older implementations of GCC.
void *x; is a valid statement.
void x; is not a valid statement.
A function that returns a pointer to void is also valid.
Why is this so?
When a variable is declared in a function, the compiler has to allocate a memory space for a variable. But when a variable is of type void, the compiler doesn't know how many bytes to allocate for this variable. So this will not work for the compiler.
However, the pointer to void is different. A pointer can be of type void which can be read as an int or a double or a float or a short or a char at the time of reading. In this case, explicit typecasting required or automatic type promotion is done by the compiler.
e.g.
int
function_A( void *x )
{
int *p = (int *)x;
return *p;
}
double
function_B( void *x )
{
double *p = (double *)x;
return *p;
}
An important note: C does not allow direct typecast of dereference of void pointer.
What I mean by this is that you cannot do this:
double
function_B( void *x )
{
return (double)*x;
}
Conceptually, this makes perfect sense. But C doesn't allow this.
Related
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 don't understand why the following code generates a warning:
int func(double a, int b, char c)
{
return 0;
}
int main()
{
int(*myPointer)() = func;
return 0;
}
I thought that in C, a function with an empty parameters list mean a function that can receive an unknown number of parameters. func4 happens to receive 3 parameters. So why is it incompatible with myPointer?
Its especially confusing because the following does compile without warning:
void boo()
{
return;
}
int main()
{
int(*pointerDude)(double) = boo;
return 0;
}
What's going on?
The difference between the two cases is explained like this: if you pass a parameter to a function that accepts none, you are just consuming some memory on the stack. If you don't pass any parameter to a function that accepts a few, the latter is going to read random data from the stack.
Update: changed to community wiki to add these corrections from Pascal Cuoq:
Casts of function pointer in both directions are legal, informative warnings from the compiler notwithstanding. Calling a function with the wrong prototype is illegal in both cases. Some ABIs mandate that the function clean up the stack, in which case passing parameters to functions that accept none corrupt the stack as surely as not passing parameters to functions that expect them.
C99 6.3.2.3 par. 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 pointed-to type, the
behavior is undefined
This is the warning you get:
warning: initialization from incompatible pointer type
You are passing void which means that will require a cast. You should use the right types.
IIRC C compiler has certain assumptions which can cause very odd bugs because you're not telling it how much stack space it needs whenever that function is called. Especially since the definitions don't match this might allow someone to inadvertently read your function pointer declaration and assume no parameters and have the function return garbage. If you really want to take variable numbers of parameters use my_func(...) and varargs.
A warning is just that, a warning. Honest.
In that case, the compiler knows you have an incorrect function pointer type and it blatantly tells you that. If you try to pass a number of parameters different then 3, then it will be issued an error.
I think that the problem is related to the casting of the parameters, because char is not 32 bits. Note that if you change the char to int this works fine. It is related to automatic promotion of variables.
Compare the two:
int func();
int func(double a, int b, int c)
{
return 0;
}
and
int func();
int func(double a, int b, char c)
{
return 0;
}
gcc gives you warning for the second, but not for the first
In C an empty parameter list means that the function does not take any parameters. I believe you are confusing an empty parameter list with varargs.
Changing your first example to include the parameters will remove the warning.
int func(double a, int b, char c)
{
return 0;
}
int main()
{
int(*myPointer)(double, int, char) = func;
return 0;
}
There's the following declarations:
void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *));
int numcmp(char *, char *);
int strcmp(char *s, char *t);
Then, somewhere in the program there is the following call:
qsort((void**) lineptr, 0, nlines-1,
(int (*)(void*,void*))(numeric ? numcmp : strcmp));
(Ignore the first three arguments and numeric).
I ask what is this:
(int (*)(void*,void*))(numeric ? numcmp : strcmp)
I understand that qsort is expecting a "pointer to function that gets two void pointers and returns an int" as it's 4th argument but how what's written above satisfies that?
It seems to me like some sort of cast because it is made of two parentheses, but that would be a very odd cast. Because it takes a function and makes this function a "pointer to function that gets two void pointers and returns an int". Which is meaningless.
(I followed here the rule that a type type in parenthesis before a variable promotes the variable to that type).
So I think I just get it wrong, maybe someone can tell me how to read this, what's the order?
What's happening here is indeed a cast. Lets ignore the ternary for a second and pretend that numcmp is always used. For the purpose of this question, functions can act as function pointers in C. So if you look at the type of numeric it is actually
(int (*)(int*,int*))
In order for this to be properly used in qsort it needs to have void parameters. Because the types here all have the same size with respect to parameters and return types, it's possible to substitute on for the other. All that's needed is a cast to make the compiler happy.
(int (*)(void*,void*))(numcmp )
You've missed the trick here - the portion
(numeric ? numcmp : strcmp)
is using the ternary operator to choose which function is being called inside of qsort. If the data is numeric, it uses numcmp. If not, it uses strcmp. A more readable implementation would look like this:
int (*comparison_function)(void*,void*) =
(int (*)(void*,void*))(numeric ? numcmp : strcmp);
qsort((void**) lineptr, 0, nlines-1, comparison_function);
As others have pointed out, for
(int (*)(void*,void*))(numeric ? numcmp : strcmp)
then the following is a type cast
(int (*)(void*,void*))
and the expression is
(numeric ? numcmp : strcmp)
C declarations can be quite difficult to read, but it is possible to learn. The method is to start at the inner part and then go right one step, then left one step, continuing right, left, right, left, etc outwards until finished. You do not cross outside a parenthesis before everything inside has been evaluated. For instance for the type cast above, (*) indicates this is a pointer. Pointer was the only thing inside the parenthesis so then we evaluate to the right side outside it. (void*,void*) indicates that is a pointer to a function with two pointer arguments. Finally int indicates the return type of the function. The outer parenthesis makes this a type cast.
Update: two more detailed articles: The Clockwise/Spiral Rule and Reading C Declarations: A Guide for the Mystified.
However, the good news is that although the above is extremely useful to know, there is an extremely simple way to cheat: the cdecl program can convert from C to English description and vice versa:
cdecl> explain (int (*)(void*,void*))
cast unknown_name into pointer to function (pointer to void, pointer to void) returning int
cdecl> declare my_var as array 5 of pointer to int
int *my_var[5]
cdecl>
Exercise: What kind of variable is i?
int *(*(*i)[])(int *)
Answer in rot13 in case you do not have cdecl installed on your machine (but you really should!):
pqrpy> rkcynva vag *(*(*v)[])(vag *)
qrpyner v nf cbvagre gb neenl bs cbvagre gb shapgvba (cbvagre gb vag) ergheavat cbvagre gb vag
pqrpy>
You can do it without the function pointer cast. Here's how. In my experience, in most places, if you are using a cast, you are doing it wrong.
Note that the standard definition of qsort() includes const:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Note that the string comparator is given two 'char **' values, not 'char *' values.
I write my comparators so that casts are unnecessary in the calling code:
#include <stdlib.h> /* qsort() */
#include <string.h> /* strcmp() */
int num_cmp(const void *v1, const void *v2)
{
int i1 = *(const int *)v1;
int i2 = *(const int *)v2;
if (i1 < i2)
return -1;
else if (i1 > i2)
return +1;
else
return 0;
}
int str_cmp(const void *v1, const void *v2)
{
const char *s1 = *(const char **)v1;
const char *s2 = *(const char **)v2;
return(strcmp(s1, s2));
}
Forcing people to write casts in the code using your functions is ugly. Don't.
The two functions I wrote match the function prototype required by the standard qsort(). The name of a function when not followed by parentheses is equivalent to a pointer to the function.
You will find in older code, or code written by those who were brought up on older compilers, that pointers to functions are used using the notation:
result = (*pointer_to_function)(arg1, arg2, ...);
In modern style, that is written:
result = pointer_to_function(arg1, arg2, ...);
Personally, I find the explicit dereference clearer, but not everyone agrees.
Whoever wrote that code snippet was trying to be too clever. In his mind, he probably thinks he is being a good programmer by making a clever "one-liner". In reality, he is making code that is less readable and is obnoxious to work with over the long term and should be rewritten in a more obvious form similar to Harper Shelby's code.
Remember the adage from Brian Kernighan:
Debugging is twice as hard as writing
the code in the first place.
Therefore, if you write the code as
cleverly as possible, you are, by
definition, not smart enough to debug
it.
I do lots of performance critical coding with hard real time deadlines... and I have still not seen a place where a dense one-liner is appropriate.
I have even messed around with compiling and checking the asm to see if the one-liner has a better compiled asm implementation but have never found the one-liner to be worth it.
I would probably read it like this:
typedef int (*PFNCMP)(void *, void *);
PFNCMP comparison_function;
if (numeric)
{
comparison_function = numcmp;
}
else
{
comparison_function = strcmp;
}
qsort((void**) lineptr, 0, nlines-1, comparison_function);
The example in the question has an explicit case.
Your logic is correct i think. It is indeed casting to "pointer to function that gets two void pointers and returns an int" which is the required type by the method signature.
Both numcmp and strcmp are pointers to functions which take two char* as parameters and returns an int. The qsort routine expects a pointer to a function that takes two void* as parameters and returns an int. Hence the cast. This is safe, since void* acts as a generic pointer. Now, on to reading the declaration: Let's take your strcmp's declaration:
int strcmp(char *, char *);
The compiler reads it as strcmp is actually:
int (strcmp)(char *, char *)
a function (decaying to a pointer to a function in most cases) which takes two char * arguments. The type of the pointer strcmp is therefore:
int (*)(char *, char *)
Hence, when you need to cast another function to be compatible to strcmp you'd use the above as the type to cast to.
Similarly, since qsort's comparator argument takes two void *s and thus the odd cast!