Basically it means "nothing" or "no type"
There are 3 basic ways that void is used:
Function argument:
int myFunc(void)-- the function takes nothing.Function return value:
void myFunc(int)-- the function returns nothingGeneric data pointer:
void* data-- 'data' is a pointer to data of unknown type, and cannot be dereferenced
Note: the void in a function argument is optional in C++, so int myFunc() is exactly the same as int myFunc(void), and it is left out completely in C#. It is always required for a return value.
Basically it means "nothing" or "no type"
There are 3 basic ways that void is used:
Function argument:
int myFunc(void)-- the function takes nothing.Function return value:
void myFunc(int)-- the function returns nothingGeneric data pointer:
void* data-- 'data' is a pointer to data of unknown type, and cannot be dereferenced
Note: the void in a function argument is optional in C++, so int myFunc() is exactly the same as int myFunc(void), and it is left out completely in C#. It is always required for a return value.
I have always taken it to mean absent. Here are four cases in the C language that matches to this use of absent
R f(void)- Function parameters are absentvoid f(P)- Return value is absentvoid *p- Type of what is pointed to is absent(void) p- Usage of value is absent
Other C descendants use it for other things. The D programming language uses it for cases where an initializer is absent
T t = void;- initializing value is absent
I just began studying C and I cannot, for the life of me, understand void.
I have read and listened to many people say "It does not return a value". Ok? What is a value? Why wouldn't we want to return it? What is the difference between "void main" and "int main"? Can we just use int for everything and ignore void altogether?
In what situations is void used? In what situations is void better? etc. Please help I don't get it at all!
Videos
Basically it means "nothing" or "no type"
There are 3 basic ways that void is used:
Function argument:
int myFunc(void)-- the function takes nothing.Function return value:
void myFunc(int)-- the function returns nothingGeneric data pointer:
void* data-- 'data' is a pointer to data of unknown type, and cannot be dereferenced
Note: the void in a function argument is optional in C++, so int myFunc() is exactly the same as int myFunc(void), and it is left out completely in C#. It is always required for a return value.
The keyword void (not a pointer) means "nothing" in those languages. This is consistent.
As you noted, void* means "pointer to anything" in languages that support raw pointers (C and C++). This is an unfortunate decision because as you mentioned, it does make void mean two different things.
I have not been able to find the historical reason behind reusing void to mean "nothing" and "anything" in different contexts, however C does this in several other places. For example, static has different purposes in different contexts. There is obviously precedent in the C language for reusing keywords this way, regardless of what one may think of the practice.
Java and C# are different enough to make a clean break to correct some of these issues. Java and "safe" C# also do not allow raw pointers and do not need easy C compatibility (Unsafe C# does allow pointers but the vast majority of C# code does not fall into this category). This allows them to change things up a bit without worrying about backwards compatibility. One way of doing this is introducing a class Object at the root of the hierarchy from which all classes inherit, so an Object reference serves the same function of void* without the nastiness of type issues and raw memory management.
void and void* are two different things. void in C means exactly the same thing as it does in Java, an absence of a return value. A void* is a pointer with an absence of a type.
All pointers in C need to be able to be dereferenced. If you dereferenced a void*, what type would you expect to get? Remember C pointers don't carry any runtime type information, so the type must be known at compile time.
Given that context, the only thing you can logically do with a dereferenced void* is ignore it, which is exactly the behavior the void type denotes.
A pointer to void is a "generic" pointer type. A void * can be converted to any other pointer type without an explicit cast. You cannot dereference a void * or do pointer arithmetic with it; you must convert it to a pointer to a complete data type first.
void * is often used in places where you need to be able to work with different pointer types in the same code. One commonly cited example is the library function qsort:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base is the address of an array, nmemb is the number of elements in the array, size is the size of each element, and compar is a pointer to a function that compares two elements of the array. It gets called like so:
int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);
The array expressions iArr, dArr, and lArr are implicitly converted from array types to pointer types in the function call, and each is implicitly converted from "pointer to int/double/long" to "pointer to void".
The comparison functions would look something like:
int compareInt(const void *lhs, const void *rhs)
{
const int *x = lhs; // convert void * to int * by assignment
const int *y = rhs;
if (*x > *y) return 1;
if (*x == *y) return 0;
return -1;
}
By accepting void *, qsort can work with arrays of any type.
The disadvantage of using void * is that you throw type safety out the window and into oncoming traffic. There's nothing to protect you from using the wrong comparison routine:
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareInt is expecting its arguments to be pointing to ints, but is actually working with doubles. There's no way to catch this problem at compile time; you'll just wind up with a missorted array.
Using a void * means that the function can take a pointer that doesn't need to be a specific type. For example, in socket functions, you have
send(void * pData, int nLength)
this means you can call it in many ways, for example
char * data = "blah";
send(data, strlen(data));
POINT p;
p.x = 1;
p.y = 2;
send(&p, sizeof(POINT));
There is no function called void, but a function can be declared with a return type of void. This means that the function doesn't return a value.
void DoSomething(...)
{
....
}
Update
void can also be used to indicate to the compiler that the function does not take any arguments. For example,
float CalculatePi(void)
{
....
}
void in C has three uses:
To declare that a function does not return a value:
void foo(int x);To declare that a function does not accept parameters:
int baz(void);(DANGER WILL ROBINSON!) To declare a "universal pointer", that may be passed around as e.g. a magic cookie, or handed back to someone in a callback, there to be cast back to its original type.
int register_callback(void (*foo)(void *baz), void *bar);
register_callback is called with a pointer to a void function that expects as parameter a pointer that presumably means something to it. At some (unspecified) time in the future, that function will be called, with bar as the parameter. You see this kind of thing in certain kinds of embedded executives and reusable device drivers, although not so much anywhere.