I am trying to initialize struct sigaction
(from sigaction.h) using C++20 designated initializers, but there are compiler errors. As this is part of a larger program, I created a short example:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void onSIGINT(int signal, siginfo_t *siginfo, void *context) {
printf("Caught signal\n");
}
int main(int argc, char** argv) {
struct sigaction act = {
.sa_sigaction = onSIGINT,
.sa_flags = SA_SIGINFO
};
if(sigaction(SIGINT, &act, nullptr) != 0) {
fprintf(stderr, "Failed to listen for SIGINT\n");
return 1;
}
printf("Waiting for signal...\n");
pause();
printf("Exit\n");
return 0;
}
According to https://gcc.gnu.org/projects/cxx-status.html#cxx20 designated initializers are available in gcc8. Running g++ (v8.3.0 on Debian buster) with -std=c++2a
gives the following error:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:11:9: error: expected primary-expression before ‘.’ token
.sa_sigaction = onSIGINT,
^
main.cpp:12:9: error: either all initializer clauses should be designated or none of them should be
.sa_flags = SA_SIGINFO
^
Initializing only sa_flags
compiles successfully, initializing only sa_sigaction
fails to compile (only first error).
I also tried to initialize __sigaction_handler
directly (no using the define to access the union member):
struct sigaction act = {
.__sigaction_handler = { .sa_sigaction = onSIGINT },
.sa_flags = SA_SIGINFO
};
That produces a similar error:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:12:34: error: expected primary-expression before ‘.’ token
.__sigaction_handler = { .sa_sigaction = onSIGINT },
^
I suppose I am doing something wrong about the union inside the struct, but I can't figure out what.
I am aware that I could achieve roughly the same by zeroing the memory of the struct and then setting callback and flags, but thats not the point.
The problem is that sa_sigaction
is a macro , defined to __sigaction_handler.sa_sigaction
. This means that your code expands to .__sigaction_handler.sa_sigaction = onSIGINT
; this is valid C, where a named member initializer is allowed to have a complex structure, but it is not valid in C++20.
You can see that by #undef
ing it :
#undef sa_sigaction
.__sigaction_handler = { .sa_sigaction = onSIGINT },
However this is non-portable (undefining a standard library macro, not to mention using a double-underscore prefixed member), so I would recommend against it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.