I have a function with no parameters in C. Clang-16 suggests me to avoid function declaration without a prototype, but pthread_create
does not work anymore with prototype that has no parameters. This is the scenario:
The main.c
file tries to create a pthread from a thread_function
function:
// main.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "./thread.h"
int main(void) {
pthread_t thread_id;
pthread_create(&thread_id, NULL, thread_function, NULL);
pthread_join(thread_id, NULL);
return EXIT_SUCCESS;
}
The thread_function
function is declared in thread.h
header file:
// thread.h
#ifndef _THREAD_H_
#define _THREAD_H_
void *thread_function();
#endif // _THREAD_H_
And is defined in thread.c
file:
// thread.c
#include <stdio.h>
void *thread_function() {
printf("Hi\n");
return NULL;
}
I compiled the program with clang-16
:
$ clang-16 main.c thread.c -o thread -Wpedantic
In file included from main.c:4:
././thread.h:4:22: warning: a function declaration without a prototype is deprecated in all versions of C [-Wstrict-prototypes]
void *thread_function();
^
void
1 warning generated.
thread.c:3:22: warning: a function declaration without a prototype is deprecated in all versions of C [-Wstrict-prototypes]
void *thread_function() {
^
void
1 warning generated.
To fix warnings, I applied both suggested fixes:
// thread.h
#ifndef _THREAD_H_
#define _THREAD_H_
void *thread_function(void);
#endif // _THREAD_H_
And also in thread.c
:
// thread.c
#include <stdio.h>
void *thread_function(void) {
printf("Hi\n");
return NULL;
}
Now I can not compile the program anymore:
$ clang-16 main.c thread.c -o thread -Wpedantic
main.c:8:36: error: incompatible function pointer types passing 'void *(void)' to parameter of type 'void * _Nullable (* _Nonnull)(void * _Nullable)' [-Wincompatible-function-pointer-types]
pthread_create(&thread_id, NULL, thread_function, NULL);
^~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/pthread.h:334:31: note: passing argument to parameter here
void * _Nullable (* _Nonnull)(void * _Nullable),
^
1 error generated.
I changed the signature of the function to:
// thread.h
#ifndef _THREAD_H_
#define _THREAD_H_
void *thread_function(void *);
#endif // _THREAD_H_
And also:
// thread.c
#include <stdio.h>
void *thread_function(void *) {
printf("Hi\n");
return NULL;
}
It compiles then but it is not ANSI-compatible anymore:
$ clang-16 main.c thread.c -o thread -Wpedantic
thread.c:3:29: warning: omitting the parameter name in a function definition is a C2x extension [-Wc2x-extensions]
void *thread_function(void *) {
^
1 warning generated.
If I change the signature to void *thread_function(void *args)
it is not "a function with no parameters" anymore. How can I create pthread from a function with no parameters and still be ANSI-compatible?
Pthreads have always expected a function pointer of type void* func (void*)
regardless of what compiler or C standard you are using. If you ever did anything else, you have been doing it wrong.
void *thread_function();
is an invalid thread callback function in all versions of C and POSIX. Similarly, void *thread_function(void)
does not improve anything since it is still the wrong function type.
The last compiler message you get is because a function definition (as opposed to declaration/prototype) without explicit parameter names is nonsense. To be ISO C compatible (forget about "ANSI"), you need to name it:
void *thread_function (void* param)
Now if you aren't passing any parameters to the function you can just cast it to void to disable warnings: (void)param;
. Alternatively in upcoming C23, the parameter could be declared as [[maybe_unused]] void* param
.
If I change the signature to void *thread_function(void *args) it is not "a function with no parameters" anymore.
It never was. Pthreads demand a function with a void*
parameter, period.
What function types to use here is not some option that the programmer can decide. The correct types to use are the ones listed by the library API, man pthread_create
:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);