这是一个合法的C ++代码吗?

代码来自这里

鉴于在C ++中您可以使用C库,您会说下面的代码是合法的C ++代码吗? 如果没有,需要应用哪些更改?

此代码使用g ++编译并按预期运行。

更新:谢谢你的所有答案。 我仍然有点困惑,因为没有就此代码是否符合C ++标准达成一致。 会问另一个问题以消除我的怀疑

更新2:关闭此问题的版主:刚刚注意到问题已经结束,我觉得这很荒谬。 这是一个脚踏实地的技术问题,我收到了脚踏实地的技术答案。如果你还没有完全阅读整个主题,这里是我们已经同意的结论的直观表示:

替代文字

显然,C ++不是C的超集。

解决与编码标准有关的问题是错误的。

客户:

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #define PORT "3490" // the port client will be connecting to #define MAXDATASIZE 100 // max number of bytes we can get at once // get sockaddr, IPv4 or IPv6: void *get_in_addr(struct sockaddr *sa){ if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*)sa)->sin_addr); } return &(((struct sockaddr_in6*)sa)->sin6_addr); } int main(int argc, char *argv[]){ int sockfd, numbytes; char buf[MAXDATASIZE]; struct addrinfo hints, *servinfo, *p; int rv; char s[INET6_ADDRSTRLEN]; if (argc != 2) { fprintf(stderr,"usage: client hostname\n"); exit(1); } memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); return 1; } // loop through all the results and connect to the first we can for(p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("client: socket"); continue; } if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); perror("client: connect"); continue; } break; } if (p == NULL) { fprintf(stderr, "client: failed to connect\n"); return 2; } inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s); printf("client: connecting to %s\n", s); freeaddrinfo(servinfo); // all done with this structure if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) { perror("recv"); exit(1); } buf[numbytes] = '\0'; printf("client: received '%s'\n",buf); close(sockfd); return 0; } 

服务器:

 #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #define PORT "3490" // the port users will be connecting to #define BACKLOG 10 // how many pending connections queue will hold void sigchld_handler(int s){ while(waitpid(-1, NULL, WNOHANG) > 0); } // get sockaddr, IPv4 or IPv6: void *get_in_addr(struct sockaddr *sa){ if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*)sa)->sin_addr); } return &(((struct sockaddr_in6*)sa)->sin6_addr); } int main(void){ int sockfd, new_fd; // listen on sock_fd, new connection on new_fd struct addrinfo hints, *servinfo, *p; struct sockaddr_storage their_addr; // connector's address information socklen_t sin_size; struct sigaction sa; int yes=1; char s[INET6_ADDRSTRLEN]; int rv; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // use my IP if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); return 1; } // loop through all the results and bind to the first we can for(p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("server: socket"); continue; } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); perror("server: bind"); continue; } break; } if (p == NULL) { fprintf(stderr, "server: failed to bind\n"); return 2; } freeaddrinfo(servinfo); // all done with this structure if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } sa.sa_handler = sigchld_handler; // reap all dead processes sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } printf("server: waiting for connections...\n"); while(1) { // main accept() loop sin_size = sizeof their_addr; new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); if (new_fd == -1) { perror("accept"); continue; } inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s); printf("server: got connection from %s\n", s); if (!fork()) { // this is the child process close(sockfd); // child doesn't need the listener if (send(new_fd, "Hello, world!", 13, 0) == -1) perror("send"); close(new_fd); exit(0); } close(new_fd); // parent doesn't need this } return 0; } 

从您的评论中看起来您似乎对代码的可移植性非常感兴趣,或者“您如何确定它将在任何C ++编译器上编译而不仅仅是g ++”。

由于每个编译器都支持不同的扩展集(或者甚至是它们支持标准的不同级别,或者它们支持的标准),因此一种方法是尝试使用不同的编译器进行编译。

如果您不能这样做,您可以准确指定gcc将用于编译的哪组扩展和/或标准。 例如:

 --std=c89 --std=c90 --std=c99 --std=gnu90 (default for C compiles) --std=gnu99 --std=c++98 --std=c++0x --std=gnu++98 (default for C++ compiles) --std=gnu++0x 

可能还有其他内容,请参阅gcc文档以获取更多详细信息: http : //gcc.gnu.org/onlinedocs/gcc/Standards.html

此外,–pedantic选项可以使gcc更严格地遵守标准。

我个人认为C ++比C更具说明性,这是高度程序性的(虽然不像prolog那样具有说法性)。

服务器

 ServerAction action; Server server(action); EventLoop loop(server); loop.processes(); 

客户

 Address addr("123.45.67"); Connection connect(addr); Message message(Connection::Type::HTTP, "Plop"); connection.Send(message); 

这符合C ++标准,从这个意义上说它是合法的 C ++。

但是,这里没有任何特定于C ++的东西。 你可以用gcc轻松编译它。

我认为其他人在这里注意到的是这个代码是以程序方式编写的,而不是以面向对象的方式编写的。 大多数人将C ++与面向对象的编程相关联,而大多数讨论道德负责任的C ++编程的现代书籍都会说这是编写应用程序的一种糟糕方式。 换句话说,当面向对象的范例可用于编写这种类型的应用程序时,编写这样的程序是非常不流行的。

这个应用程序很难维护,几乎是随意写的。 一个优秀的C程序员会将这个问题分解为多个函数,而不是将大部分函数转储到main()中。 它作为如何做客户端服务器的一个例子 ,但我会犹豫写这样的新代码。

你不是在编写C ++,你正在利用这样一个事实:符合条件,干净的C代码将编译成C ++而没有任何问题。 有些地方C ++与C不同,但编译器会在这些情况下对你大喊大叫。 您可以使用它作为基础,在其基础上编写一些有效的C ++; 否则,没有什么特别的事情发生。

这是有效的,但不是C ++首选样式。

例如,所有标准C库都应包含在 ,而不是

另一个例子,当代码使用常量整数时,它使用#define。

如果我在苏格兰拜访你并用我的葡萄牙口音和(简短的)英语词汇说苏格兰语……你会说我说苏格兰语吗?

假设每个人都理解我,我理解每个人:-)

使用C ++,您可以使用更好的类型检查function来避免像void * ,# define等。

但由于它不使用独有的Cfunction,因此它使用g ++进行编译。

它的’C’代码也符合C ++中的兼容子集。

如果它编译它是合法的,没有编译器错误,但在我看来,你对’合法’有不同的含义。

我不太明白这个问题。 我想你问你是否应该继续使用它而不做任何改动,而不用担心 – 在这种情况下我会说是的。 C ++是C的超集 – 如您所见,任何有效的C代码都是有效的C ++代码。

按照惯例,标准标题有一个新的格式 –

 #include  

 #include  

但这不是绝对必要的。 无论如何,你不能用unistd和sys / headers做到这一点。

因此,如果您在询问是否可以安全地继续使用它 – 请继续使用它,但您可能希望将errno.h更改为cerrno,将stdio.h更改为cstdio,依此类推。