C - 如何在宏中使用多个函数?
C - How to use multiple functions in macros?
目前正在用 c 构建一个简单的网络服务器。
为了改进我想使用 makros 的代码,特别是我想在单个 makro 中使用多个函数来打印错误消息并随后退出程序。
下面的代码没有迂腐的错误信息,但我想知道为什么 ISO-C 禁止这个或者我的错误在哪里。
编译器信息:
gcc -O0 -g3 -pedantic -pedantic-errors -Wall -Wextra -Werror error_makro.c
代码:
#define CHECK(x,m) ((x) < 0) ? ({perror(m); exit(1);}) : (NULL)
void createWebSocket(simpleWebServer *self){
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
CHECK(getaddrinfo(NULL, self->port, &hints, &res), "getaddrinfo");
if((self->serverSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0){
perror("socket");
exit(2);
}
if(bind(self->serverSocket, res->ai_addr, res->ai_addrlen) < 0){
perror("bind");
exit(3);
}
if(listen(self->serverSocket, BACKLOG) == -1){
perror("listen");
exit(4);
}
freeaddrinfo(res);
}
错误信息:
error_makro.c: In function ‘main’:
error_makro.c:6:32: error: ISO C forbids braced-groups within expressions [-Wpedantic]
6 | #define CHECK(x,m) ((x) < 0) ? ({perror(m); exit(1);}) : (NULL)
| ^
error_makro.c:11:5: note: in expansion of macro ‘CHECK’
11 | CHECK(-1, "test");
| ^~~~~
error_makro.c:6:56: error: ISO C forbids conditional expr with only one void side [-Wpedantic]
6 | #define CHECK(x,m) ((x) < 0) ? ({perror(m); exit(1);}) : (NULL)
| ^
error_makro.c:11:5: note: in expansion of macro ‘CHECK’
11 | CHECK(-1, "test");
| ^~~~~
#define CHECK(x,m) ((x) < 0) ? ({perror(m); exit(1);}) : ({(NULL);})
将工作:
https://godbolt.org/z/Kxed3b55r
双方类型相同void
。您不能使用 -pedantic
作为编译时标志,因为 ISO C forbids braced-groups within expressions
.
在这种情况下我建议:
#define CHECK(x,m) do { if ((x) < 0) {perror(m); exit(1);} } while (0)
在标准 C 中,;
标记表达式的结束。因此括号不能包含 ;
,因为 syntax-wise 括号的 (
和 )
都需要在完整表达式中。
({ ... })
是一个“语句表达式”,一个non-standard GNU扩展,允许多个以;
结尾的表达式在里面同时返回最后一个的结果表达式。
在 -std=c17 -pedantic
模式下,gcc 变成兼容的 C 编译器,因此所有 GNU 扩展都被禁用。
请注意,很可能会使用标准 C 来代替这些“语句表达式”。您通常可以使用逗号运算符链接一堆函数调用:(perror(m), exit(1))
- 这也是 returns 最后一个 (right-most) sub-expresion.
的结果
更好的是,使用实际函数,在这种情况下这可能是最正确的解决方案。
目前正在用 c 构建一个简单的网络服务器。 为了改进我想使用 makros 的代码,特别是我想在单个 makro 中使用多个函数来打印错误消息并随后退出程序。
下面的代码没有迂腐的错误信息,但我想知道为什么 ISO-C 禁止这个或者我的错误在哪里。
编译器信息:
gcc -O0 -g3 -pedantic -pedantic-errors -Wall -Wextra -Werror error_makro.c
代码:
#define CHECK(x,m) ((x) < 0) ? ({perror(m); exit(1);}) : (NULL)
void createWebSocket(simpleWebServer *self){
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
CHECK(getaddrinfo(NULL, self->port, &hints, &res), "getaddrinfo");
if((self->serverSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0){
perror("socket");
exit(2);
}
if(bind(self->serverSocket, res->ai_addr, res->ai_addrlen) < 0){
perror("bind");
exit(3);
}
if(listen(self->serverSocket, BACKLOG) == -1){
perror("listen");
exit(4);
}
freeaddrinfo(res);
}
错误信息:
error_makro.c: In function ‘main’:
error_makro.c:6:32: error: ISO C forbids braced-groups within expressions [-Wpedantic]
6 | #define CHECK(x,m) ((x) < 0) ? ({perror(m); exit(1);}) : (NULL)
| ^
error_makro.c:11:5: note: in expansion of macro ‘CHECK’
11 | CHECK(-1, "test");
| ^~~~~
error_makro.c:6:56: error: ISO C forbids conditional expr with only one void side [-Wpedantic]
6 | #define CHECK(x,m) ((x) < 0) ? ({perror(m); exit(1);}) : (NULL)
| ^
error_makro.c:11:5: note: in expansion of macro ‘CHECK’
11 | CHECK(-1, "test");
| ^~~~~
#define CHECK(x,m) ((x) < 0) ? ({perror(m); exit(1);}) : ({(NULL);})
将工作:
https://godbolt.org/z/Kxed3b55r
双方类型相同void
。您不能使用 -pedantic
作为编译时标志,因为 ISO C forbids braced-groups within expressions
.
在这种情况下我建议:
#define CHECK(x,m) do { if ((x) < 0) {perror(m); exit(1);} } while (0)
在标准 C 中,;
标记表达式的结束。因此括号不能包含 ;
,因为 syntax-wise 括号的 (
和 )
都需要在完整表达式中。
({ ... })
是一个“语句表达式”,一个non-standard GNU扩展,允许多个以;
结尾的表达式在里面同时返回最后一个的结果表达式。
在 -std=c17 -pedantic
模式下,gcc 变成兼容的 C 编译器,因此所有 GNU 扩展都被禁用。
请注意,很可能会使用标准 C 来代替这些“语句表达式”。您通常可以使用逗号运算符链接一堆函数调用:(perror(m), exit(1))
- 这也是 returns 最后一个 (right-most) sub-expresion.
更好的是,使用实际函数,在这种情况下这可能是最正确的解决方案。