Function with 0 arguments - void vs void*? - c++

I know that you can declare a function without any arguments simply like this:
void test()
{
cout << "Hello world!!" << endl;
}
But I have also seen
void test(void)
{
cout << "Hello world!!" << endl;
}
and
void test(void*)
{
cout << "Hello world!!" << endl;
}
My question is: What is the difference between using void and void* here?

The one an only form for a function with no parameters in C++ should be
void test();
The form:
void test(void)
That is how you define a function with no parameters in c. But in C++ use this form only for interfacing with c:
extern "C"
{
void test(void);
}
This form:
void test(void*)
Is not a function with no arguments. It has an argument of type void* that is unnamed. It expects a void* pointer when called.
Have a look here for an explanation of what a void* pointer is: What does void* mean and how to use it?

What is the difference between using void and void* here?
When the argument type is void, the function must be called without any arguments.
When the argument type is void*, the function must be called with an argument that is a void* or can be converted to a void*.
void stands for "nothing" but void* does not stand for "pointer to nothing". In fact, it's quite the contrary. void* stands for pointer to anything except void. It is oxymoronic but that's how the language defines those two.

My question is: What is the difference between using void and void* here?
(void) parameter list is same as empty parameter list. The void here does nothing in C++ and is unnecessary unless compatibility with C is needed - see the second part of the answer.
(void*) does not accept 0 arguments. It accepts 1 argument. The type of the parameter is void* which is a pointer type.
Why is it like this?
Because of backwards compatibility with C. In C, (void) is the only way to declare a function that only accepts empty argument list. () parameter list declares any function without specifying the parameters. The number of parameters could be any, including 0. The use of () parameter list in C is becoming an obsolete feature.
Quote from C11 standard draft N1548:
Function declarators (including prototypes)
An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
Future language directions
Function declarators
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
Function definitions
The use of function definitions with separate parameter identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.
C is this way because of backward compatibility with older versions (pre-standard) of C where parameter lists weren't declared.

In C++ these two declarations of a function
void test();
and
void test(void);
are equivalent and mean that the function does not take any arguments.
In C, the first function declaration declares a function with an empty identifier list, and the second function declaration declares a function with a parameter type list that in fact has no parameters.
According to the C Standard (6.9.1 Function definitions):
5 If the declarator includes a parameter type list, the declaration of
each parameter shall include an identifier, except for the special
case of a parameter list consisting of a single parameter of type
void, in which case there shall not be an identifier. No declaration
list shall follow.
This declaration of the function (that is also its definition)
void test(void*)
{
//...
}
has 1 parameter, an object of type void * (pay attention to that pointers are always complete types), that is not used within the function.
This declaration is valid in C++, and is not valid in C, because in C each function parameter in a function declaration with a parameter type list that is at the same time its definition shall have an identifier, except in the case when a void parameter is used, as specified in the quote above.
In C you may use such a declaration only when the declaration is not at the same type its definition.
So in C for example you may write like
void test(void*); // declaratipon
and then
void test( void *ptr ) // declaration and definition
{
//...
}

Related

Why is an asterisk optional when defining the type of a single function pointer but mandatory when that function pointer is an array element?

The compiler is permissive in allowing interchanging of "function" and "function pointer" when defining a single function parameter (optional asterisk in typedef), but strict when these function pointers are elements of arrays (mandatory asterisk in typedef):
typedef void(Action)();
// typedef void(*Action)();
// Works with either typedef
void doAction(Action f) {
f();
}
// Only works with latter typedef
void doFirstAction(Action f_array[2]) {
f_array[0]();
}
clang 15 output:
error: 'f_array' declared as array of functions of type 'Action' (aka 'void ()')
void doFirstAction(Action f_array[2]) {
^
I'd expect these asterisk rules to be consistent between single functions and arrays of functions, where each typedef would work for either none or both cases.
I understand that this rule is part of the C++ standard:
There shall be no arrays of functions, although there can be arrays of pointers to functions.
But I assume there's a similar rule about how only "function pointers" and not just "functions" can be passed to other functions, yet there's more flexibility in syntax for that case.
Follow-up to: Declaring an array of functions of type void C++

How can I receive a void parameter in function definition, C or C++?

How can I receive in a function definition when the one of the parameter in function call is void?
The scenario is that one of my projects, in a function call one of the parameters is void. That section I could not change.
I can change only the function declaration or the function definition, but I still confused what I need to change.
Please help
Below code is not a executable one:
for ex:
#include <stdio.h>
void test(void, int a) {
printf("%d", a);
}
int main() {
test(void, 32);
}
You can't. That is not valid C:
<source>:2:11: error: 'void' must be the only parameter
2 | void test(void,int a)
| ^~~~
Same goes for C++:
<source>:2:11: error: invalid use of type 'void' in parameter declaration
2 | void test(void,int a)
| ^~~~
The only valid use of void as parameter is on it's own, as in:
int bar();
int foo(void);
In C this means the function bar takes an undetermined number of arguments while foo does not take any arguments. In C++ both are equivalent.
void is an incomplete type and cannot be used as the parameter of a function(in both C and C++) with the exception that if void is the only parameter of that function. This can be seen from the following quoted statements.
C++
From function's documentation:
Parameter list determines the arguments that can be specified when the function is called. It is a comma-separated list of parameter declarations, each of which has the following syntax:
5 Indicates that the function takes no parameters, it is the exact synonym for an empty parameter list: int f(void); and int f(); declare the same function. Note that the type void (possibly cv-qualified) cannot be used in a parameter list otherwise: int f(void, int); and int f(const void); are errors (although derived types, such as void* can be used). In a template, only non-dependent void type can be used (a function taking a single parameter of type T does not become a no-parameter function if instantiated with T = void).
Note also that there is a semantic difference(between C++ & C) in case void is used as a parameter of a function and is the only parameter as shown in the following example:
int func(void); //declaration of func that takes no parameter and has the return type of void
int foo(); //declaration of foo that takes no parameter and has the return type of void
C
From function declaration's documentation:
parameters cannot have type void (but can have type pointer to void). The special parameter list that consists entirely of the keyword void is used to declare functions that take no parameters.
int f(void); // OK
int g(void x); // Error
Unlike in C++ and function definitions (since C23), the declarators f() and f(void) have different meaning: the declarator f(void) is a new-style (prototype) declarator that declares a function that takes no parameters. The declarator f() is a declarator that declares a function that takes unspecified number of parameters (unless used in a function definition)

What difference between void(void) and void(*)(void)?

void(*)(void) is a function pointer while I suppose void(void) is also a way to represent function type. It is used as template parameter in std::function <functional>
What is void(void) and how it is different from void(*)(void)?
What is void(void) and how it is different from void(*)(void)?
They are distinct types. Although the former(void(void)) can be implicitly converted to the latter(void(*)(void)) in many contexts.
The type void(void) is called a function type. The following are also function types:
int (int, int) //this is a function type
void(int) //this is a function type as well
On the other hand, void (*)(void) is a pointer to a function type. That is, it is a pointer that points to a function with 0 parameters and return type of void.
TL;DR
The void(void) is a specification of a function type, it's
signature.
The void(*)(void) is a pointer to function.
These are distinct.
First, let's start by saying, that sometimes the void(void) will be automatically treated as a pointer to function (i.e. in a parameter list). We still can be explicit and use the void(*)(void), but the void(void) will be an equivalent in these cases.
// Here, we explicitly state that the f is a pointer to function
void foo(void (*f)(void), int i);
// Equivalent, f is automatically treated as a pointer to the function
void foo(void f(void), int i);
This will not be the case for the mentioned std::function for example. The types of the two are different, yet may have similar behavior (i.e. we can use the function call operator on a pointer to function).
void bar();
// Prints 1
std::cout << std::is_same<void(void), decltype(bar)>::value << '\n';
// Prints 1 as well
// Note the pointer type specifier
std::cout << std::is_same<void(*)(void), decltype(bar)*>::value << '\n';
// Prints 0
// Note the absence of the pointer type specifier
std::cout << std::is_same<void(*)(void), decltype(bar)>::value << '\n';
And particularly:
// Ok
std::function<decltype(bar)> fn1 = bar;
// error: variable ‘std::function<void (*)()> fn2’ has initializer but incomplete type
std::function<decltype(bar)*> fn2 = bar;
Note, that we can however "store" a pointer to a member function in std::function, but even then the template's parameter still won't be of a pointer to function type, but a plain function signature.
struct MyType {
void func(int) {}
};
int main() {
// Note, we can't have a member function without an instance of the type
// Thus we specify the usually implicit first param and the explicit int param
std::function<void(MyType&, int)> fn_mem = &MyType::func;
MyType my_object;
fn_mem(my_object, 21);
}
For more on std::function please refer to the reference. In short, the use of the std::function instead of the function pointers has the same moto as using the smart pointers instead of the raw pointers.
You may wonder on other uses of the void(void) or int(int) style function type specifications, so here's another example you may see often:
using func_t = int(int);
// func_ptr_func return a pointer to the func_t type alias
func_t* func_ptr_func();
N.B. unlike in the case of a parameter, the compiler won't treat the function type in a return as a pointer to function type. Thus, we must explicitly specify the pointer type in case of the return.
// Here, baz is a function that doesn't take any agruments
// And returns a pointer to a function that takes an int argument and "returns" void
void (*baz())(int);
for void fun(){}, std::is_same_v<void(void)>, decltype(fun)> is true; and std::is_same_v<void(*)(void)>, decltype(&fun)> is true. In fact, those are their real types. However, the standard approve you convert an object that has type void(void) to void(*)(void) implicitly (so you can even write (******funptr)()), that's why we always confuse them.

Omit void as function result in C++

In C/C++ there are two ways to declare a function that returns nothing.
First one is to declare a function without arguments:
// no arguments
void f() {
}
The second one is to declare a function that takes void:
// still no arguments
void f(void) {
}
However, this is not true for the function result: we can't omit void at the beginning of the function like this:
// returns nothing
f() {
return; // yay
}
So, is there absolutely no way to omit void at the beginning of the function like with the function arguments?
So, is there absolutely no way to omit void at the beginning of the function like with the function arguments?
No, there absolutely isn't. There is no function declaration syntax that doesn't have the return type in C++ nor in C99 or later. There used in C prior to C99, but the default return type would have been int rather than void.
Note that declarations void f() and void f(void) are not equivalent in C. Former declares a function with unspecified parameters while the latter declares a function with empty parameter list. In C++, both declare a function with empty parameter list.

Do I have to specify a '*' before function pointer?

When I'm passing function as parameter to other functions in c++ , do I have to specify it as
void callOtherFunctions(void f());
or
void callOtherFunctions(void (*f)());
I have no idea what happens under the hood , so I tried running both versions with a simple program as below , replacing the necessary part for 2nd run.
#include <iostream>
using namespace std;
void printHello();
void callOtherFunctions(void f());
int main() {
callOtherFunctions(printHello);
return 0;
}
void printHello(){
std::cout<<"\n Hello World";
}
void callOtherFunctions(void f()){
for (int i=0;i<5;++i){
f();
}
}
and to my surprise , both execute with same output and no warnings. So which is the preferred way , or correct way ( in case I'm doing something wrong ). And what actually happens in each case , when I pass pointer - does it executes address function there and when I pass function - does it copies down whole function there? or something else?
Here is Ideone Link
void callOtherFunctions(void f());
and
void callOtherFunctions(void (*f)());
are identical. Quoting N1570,
§6.7.6.3/8 A declaration of a parameter as "function returning type"
shall be adjusted to "pointer to function returning type", as in
6.3.2.1.
I would prefer the function pointer syntax because more people would be familiar with it and it's explicit what you mean. To answer your second question, a conversion also happens in certain cases (informally known as "decay"):
§6.3.2.1/4 A function designator is an expression that has function
type. Except when it is the operand of the sizeof operator, the
_Alignofoperator,65) or the unary & operator, a
function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".
Function parameter declarations are somewhat unusual; the compiler will adjust some of the declared types. This is one of them: function parameters of function type are adjusted to the corresponding pointer type.
Other common adjustments to function parameters are array to pointer type, and removing top-level const:
int foo(int a[5]); // a is a pointer
int foo(const int a); // foo() can be called with a non-const int argument.