如果我尝试使用C标准之一进行编译,就会得到此信息:
-std=c99
,-std=c11
或-std=c17
。
如果我删除它们,编译效果很好,或者如果我使用-std=gnuXX
也可以
为什么会这样,因为我无法修复。
program.c:
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#define PORT "5555"
#define BACKLOG 5
int getAdr_fd(struct addrinfo server, struct addrinfo **res );
int create_fd( struct addrinfo **res );
int accept_fd( struct sockaddr_storage *their_addr, int *sockfd );
int list_fd( int *sockfd );
int bind_fd( struct addrinfo **res, int *sockfd );
ssize_t write_fd( const char *const msg, int *new_fd );
int main(void){
const char *msg = "Hello socket World!\n";
struct sockaddr_storage their_addr;
struct addrinfo server, *res;
int sockfd, new_fd;
/* create a socket: */
getAdr_fd( server, &res );
sockfd = create_fd( &res );
/* Bind */
bind_fd( &res, &sockfd );
/* Listen */
list_fd( &sockfd );
/* Accept connection: */
new_fd = accept_fd( &their_addr, &sockfd );
/* Write */
write_fd( msg, &new_fd );
/* close: */
close(sockfd);
freeaddrinfo(res);
}
int getAdr_fd(struct addrinfo server, struct addrinfo **res ){
int getfd;
/* Create address structs with getaddrinfo(): */
memset(&server, 0, sizeof server);
server.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
server.ai_socktype = SOCK_STREAM;
server.ai_flags = AI_PASSIVE; // fill in my IP for me
getfd = getaddrinfo( NULL, PORT, &server, res);
if (getfd != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror( getfd ));
exit(EXIT_FAILURE);
}else{
printf("getaddrinfo() \tOK\n");
return getfd;
}
}
int create_fd( struct addrinfo **res ){
int sockfd = socket((*res)->ai_family, (*res)->ai_socktype, (*res)->ai_protocol);
if (sockfd == -1 ){
printf("Error, socket()\n");
exit ( EXIT_FAILURE );
}else{
printf("socket() \tOK\n");
return sockfd;
}
}
int bind_fd( struct addrinfo **res, int *sockfd ){
int bindfd = bind(*sockfd, (*res)->ai_addr, (*res)->ai_addrlen);
if (bindfd == -1 ){
printf("Error, bind(), check line 34\n");
exit ( EXIT_FAILURE );
}else{
printf("bind() \t\tOK\n");
return bindfd;
}
}
int accept_fd( struct sockaddr_storage *their_addr, int *sockfd ){
int new_fd;
socklen_t addr_size = sizeof( *their_addr );
new_fd = accept(*sockfd, (struct sockaddr *)their_addr, &addr_size);
if (new_fd == -1 ){
printf("Error, accept()\n");
exit ( EXIT_FAILURE );
}else{
printf("accept() \tOK\n");
return new_fd;
}
}
int list_fd( int *sockfd ){
int listfd = listen(*sockfd, BACKLOG);
if (listfd == -1 ){
printf("Error, listen()\n");
exit ( EXIT_FAILURE );
}else{
printf("listen() \tOK\n");
return listfd;
}
}
ssize_t write_fd( const char *const msg, int *new_fd ){
size_t len = strlen(msg);
ssize_t wrtfd;
wrtfd = write(*new_fd, msg, len );
if (wrtfd == -1 ){
printf("Error, write()\n");
exit ( EXIT_FAILURE );
}else{
printf("write() \tOK\n");
}
return wrtfd;
}
编译器标志:
-Wpedantic -Wall -Wextra -Werror -std=c17 -Wstrict-prototypes -Wmissing-prototypes -Wmisleading-indentation -Wduplicated-cond -Wold-style-definition -Wconversion -Wshadow -Winit-self -Wfloat-equal -Wwrite-strings -Wcast-align=strict -Wformat -O0 -g
输出:
program.c:14:22: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror] int getAdr_fd(struct addrinfo server, struct addrinfo **res ); ^~~~~~~~ program.c:15:23: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror] int create_fd( struct addrinfo **res ); ^~~~~~~~ program.c:18:21: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror] int bind_fd( struct addrinfo **res, int *sockfd ); ^~~~~~~~ program.c: In function ‘main’: program.c:24:21: error: storage size of ‘server’ isn’t known struct addrinfo server, *res; ^~~~~~ program.c:28:16: error: type of formal parameter 1 is incomplete getAdr_fd( server, &res ); ^~~~~~ program.c:28:24: error: passing argument 2 of ‘getAdr_fd’ from incompatible pointer type [-Werror=incompatible-pointer-types] getAdr_fd( server, &res ); ^~~~ program.c:14:57: note: expected ‘struct addrinfo **’ but argument is of type ‘struct addrinfo **’ int getAdr_fd(struct addrinfo server, struct addrinfo **res ); ~~~~~~~~~~~~~~~~~~^~~ program.c:29:25: error: passing argument 1 of ‘create_fd’ from incompatible pointer type [-Werror=incompatible-pointer-types] sockfd = create_fd( &res ); ^~~~ program.c:15:34: note: expected ‘struct addrinfo **’ but argument is of type ‘struct addrinfo **’ int create_fd( struct addrinfo **res ); ~~~~~~~~~~~~~~~~~~^~~ program.c:32:14: error: passing argument 1 of ‘bind_fd’ from incompatible pointer type [-Werror=incompatible-pointer-types] bind_fd( &res, &sockfd ); ^~~~ program.c:18:32: note: expected ‘struct addrinfo **’ but argument is of type ‘struct addrinfo **’ int bind_fd( struct addrinfo **res, int *sockfd ); ~~~~~~~~~~~~~~~~~~^~~ program.c:45:5: error: implicit declaration of function ‘freeaddrinfo’ [-Werror=implicit-function-declaration] freeaddrinfo(res); ^~~~~~~~~~~~ program.c:24:21: error: unused variable ‘server’ [-Werror=unused-variable] struct addrinfo server, *res; ^~~~~~ program.c: At top level: program.c:48:23: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror] int getAdr_fd(struct addrinfo server, struct addrinfo **res ){ ^~~~~~~~ program.c:48:32: error: parameter 1 (‘server’) has incomplete type int getAdr_fd(struct addrinfo server, struct addrinfo **res ){ ~~~~~~~~~~~~~~~~^~~~~~ program.c: In function ‘getAdr_fd’: program.c:56:23: error: ‘AI_PASSIVE’ undeclared (first use in this function); did you mean ‘AF_WANPIPE’? server.ai_flags = AI_PASSIVE; // fill in my IP for me ^~~~~~~~~~ AF_WANPIPE program.c:56:23: note: each undeclared identifier is reported only once for each function it appears in program.c:58:13: error: implicit declaration of function ‘getaddrinfo’; did you mean ‘getAdr_fd’? [-Werror=implicit-function-declaration] getfd = getaddrinfo( NULL, PORT, &server, res); ^~~~~~~~~~~ getAdr_fd program.c:60:46: error: implicit declaration of function ‘gai_strerror’; did you mean ‘strerror’? [-Werror=implicit-function-declaration] fprintf(stderr, "getaddrinfo: %s\n", gai_strerror( getfd )); ^~~~~~~~~~~~ strerror program.c:60:40: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Werror=format=] fprintf(stderr, "getaddrinfo: %s\n", gai_strerror( getfd )); ~^ ~~~~~~~~~~~~~~~~~~~~~ %d program.c:48:32: error: unused parameter ‘server’ [-Werror=unused-parameter] int getAdr_fd(struct addrinfo server, struct addrinfo **res ){ ~~~~~~~~~~~~~~~~^~~~~~ program.c: At top level: program.c:68:23: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror] int create_fd( struct addrinfo **res ){ ^~~~~~~~ program.c:68:5: error: conflicting types for ‘create_fd’ int create_fd( struct addrinfo **res ){ ^~~~~~~~~ program.c:15:5: note: previous declaration of ‘create_fd’ was here int create_fd( struct addrinfo **res ); ^~~~~~~~~ program.c: In function ‘create_fd’: program.c:69:31: error: dereferencing pointer to incomplete type ‘struct addrinfo’ int sockfd = socket((*res)->ai_family, (*res)->ai_socktype, (*res)->ai_protocol); ^~ program.c: At top level: program.c:79:21: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror] int bind_fd( struct addrinfo **res, int *sockfd ){ ^~~~~~~~ program.c:79:5: error: conflicting types for ‘bind_fd’ int bind_fd( struct addrinfo **res, int *sockfd ){ ^~~~~~~ program.c:18:5: note: previous declaration of ‘bind_fd’ was here int bind_fd( struct addrinfo **res, int *sockfd ); ^~~~~~~ program.c: In function ‘bind_fd’: program.c:80:38: error: dereferencing pointer to incomplete type ‘struct addrinfo’ int bindfd = bind(*sockfd, (*res)->ai_addr, (*res)->ai_addrlen); ^~ cc1: all warnings being treated as errors
我注意到的另一个奇怪的事情是:
program.c:45:5: error: implicit declaration of function ‘freeaddrinfo’ [-Werror=implicit-function-declaration]
freeaddrinfo(res);
但是其中包含文件:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.
Linux Mint 19,GCC-8.0.1。
答案 0 :(得分:2)
getaddrinfo
函数以及扩展的struct addrinfo
类型由POSIX指定。这意味着它们不属于C标准。
因此,当您指定-std=c99
,-std=c11
或-std=c17
时,它将排除那些类型,因为它们不是标准指定的。指定-std=gnuxx
选项包括这些类型的定义。
答案 1 :(得分:1)
这与glibc错误接壤。尽管struct addrinfo
确实是C标准的一部分,但<netdb.h>
也不是C标准的一部分,所以在该标头中定义它(对非常旧的POSIX版本而言)不会有任何危害。>
如果使用-D_GNU_SOURCE
进行编译,您仍然可以指定任何C标准选项并获得GNU扩展。请参阅glibc文档和手册页: