问题代码如下,当时我是想用libevent在win32上监听一个端口的输入。
/* * Compile with: * cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent * see * http://d.hatena.ne.jp/mtaneda/20090302/1235998584 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include <sys/types.h> #include <sys/stat.h> #ifndef WIN32 #include <sys/queue.h> #include <unistd.h> #include <sys/time.h> #else #include <winsock.h> #include <windows.h> #endif #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <event.h> static void read_handler(int fd, short event, void *arg) { char buf[256] = {0}; struct event *ev; ZeroMemory(buf, sizeof(buf)); ev = (struct event*)arg; if(event & EV_READ) { if(recv(fd, buf, sizeof(buf), 0)<=0) { event_del(ev); free(ev); closesocket(fd); } else { printf("[read_handler] read=%s\n", buf); } } } static void accept_handler(int fd, short event, void *arg) { struct sockaddr_in addr; struct event *new_ev; int new_fd; int addrlen; addrlen = sizeof(addr); if(event & EV_READ) { printf("[accept_handler]\n"); new_fd = accept(fd, (struct sockaddr*)&addr, &addrlen); new_ev = malloc(sizeof(struct event)); event_set(new_ev, new_fd, EV_READ|EV_PERSIST, read_handler, new_ev); event_add(new_ev, NULL); } } int main (int argc, char **argv) { struct event ev; SOCKET sock; int on; int rc; struct sockaddr_in addr; int server_port = 8888; WORD version = MAKEWORD (1,1); WSADATA wsadata; WSAStartup (version, &wsadata); sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("socket() failed"); WSACleanup(); exit(-1); } rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); if (rc < 0) { perror("setsockopt() failed"); closesocket(sock); WSACleanup(); exit(-1); } rc = ioctlsocket(sock, FIONBIO, &on); if (rc < 0) { perror("ioctl() failed"); closesocket(sock); WSACleanup(); exit(-1); } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(server_port); rc = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); if (rc < 0) { perror("bind() failed"); closesocket(sock); WSACleanup(); exit(-1); } rc = listen(sock, 32); if (rc < 0) { perror("listen() failed"); closesocket(sock); WSACleanup(); exit(-1); } event_init(); event_set(&ev, (int)socket, EV_READ | EV_PERSIST, accept_handler, &ev); event_add(&ev, NULL); event_dispatch(); closesocket(sock); WSACleanup(); return (0); }
这个程序并没有在event_dispatch()处进入监听状态,而是在main函数最后的return (0);处退出,
后来发现bug其实在这里
event_init(); event_set(&ev, (int)socket, EV_READ | EV_PERSIST, accept_handler, &ev); event_add(&ev, NULL);
我在重命名socket对象的名称时忘记改这里。
结果代码把socket这个函数显式地转换为int型,
当时以为强制转换是必须,但事实上不是。
libevent在运行时也没有发现这个问题,于是直接退出event_dispatch()循环。
正确的写法是
event_init(); event_set(&ev, sock, EV_READ | EV_PERSIST, accept_handler, &ev); event_add(&ev, NULL);
结论是:
C代码中任何显式和隐式的类型转换都需要加倍小心,尤其是在重构代码更改变量名的时候。
尽量避免类型转换,不要完全依赖某个特定的C编译器的检查(这里我使用的是VC2008)。
相关推荐
### C语言数组访问及强制转换 #### 摘要与背景 本文主要探讨了C语言中的数组访问机制及其与强制类型转换之间的关系。通过具体的编程示例,文章深入解析了一个特殊的问题:如何将一个指向一维整型数组的指针转化为...
static_cast:用于“良性”和“适度良性”的转换,包括不用强制转换 const_cast:用于“const”和/或“volatile”进行转换 reinterpret_cast:转换为完全不同的意思。为了安全的使用它,关键必须转换回原来的类型。...
自动转换(也称为隐式转换)和强制转换(显式转换)是C语言中两种主要的类型转换方式,它们都有各自的规则和应用场景。让我们深入探讨一下这两个主题。 **自动转换(隐式转换)** 自动转换是指在某些特定情况下,...
### 数据类型的强制转换实例 本篇文章将通过一个具体的C++代码...以上内容为我们展示了在C++中如何使用强制类型转换处理复杂的数据类型转换问题。这种技术在实际开发中非常有用,尤其是在处理涉及多态和继承的场景时。
C语言中强制数据类型转换是非常重要的,需要逐步进行,有些是自然的转型,有些需要根据需要强制转换。下面我们将详细讨论数据类型转换的规则和机制。 首先,需要了解数据类型转换的规则。在C语言中,数据类型转换...
### 强制转换指针类型 #### 指针与函数指针的本质 在计算机编程中,特别是C/C++语言中,指针是一种非常重要的数据类型。它存储的是内存地址而不是具体的值。对于指针的理解至关重要,因为它涉及到如何有效地访问和...
显式转换,又称为强制转换,是程序员通过类型转换运算符显式指定的类型转换。强制转换通常用于确保数据类型的明确性,或用于解决类型不匹配的问题。显式转换需要程序员明确知道转换的后果,因为不当的转换可能导致...
在C语言中,类型强制转换的语法是`(type)expression`,其中`type`是你想要转换的目标类型,`expression`是要转换的表达式。在上述代码中,`sum = sum + (double)((n+1)/n);`这一行, `(double)`就是一个类型强制转换...
在这里,`(int)c` 将 `c` 从 `double` 类型强制转换为 `int` 类型,丢弃了小数部分,因此输出结果是 83。 2. 另一个强制转换的例子: ```java double a = 81.29; int b = 2; int c = (int)(a + b); ``` 这里,`...
二、显式类型转换(强制类型转换) 1. `(类型名)` `(表达式)`:这是C语言中显式类型转换的基本语法。例如,`(float)5` 将整数5转换为浮点数。这种转换在需要精确控制数据类型或者避免隐式转换带来的问题时使用。 2...
在C语言中,强制类型转换是一项重要的编程技巧,它允许我们显式地将一个数据类型转换为另一个数据类型。在“C强制类型转换_C教程共5页.pdf.zip”这个压缩包中,我们可以预见到它包含了关于C语言强制类型转换的详细...
3. **避免隐式转换导致的错误**:当类型转换可能引起意料之外的行为时,如可能导致精度损失或溢出,可以使用强制转换明确指定预期行为。 ### 指针类型转换 (Pointer Type Conversion) 在C语言中,指针类型转换允许...
在C语言中,强制类型转换是一种重要的编程技巧,它允许程序员显式地将一个数据类型转换为另一种数据类型。在教学过程中,理解并熟练运用强制类型转换运算对于掌握C语言至关重要。本文主要探讨了强制类型转换在不同...
- 强制转换时未考虑数据溢出,可能导致程序崩溃或产生不可预期的结果。 因此,在教学中,强调数据类型转换的重要性,理解和熟练应用转换规则,以及注意转换中可能遇到的问题,对提高编程技能和编写健壮的C语言程序...
- 例如 `(double)a` 将变量 `a` 强制转换为 `double` 类型。 - 强制类型转换可能会导致精度损失或溢出,因此需要谨慎使用。 3. **具体转换规则**: - **浮点型与整型**:浮点数转换为整数时,小数部分被舍去;...
显式转换需要强制转换运算符,而且强制转换会造成数据丢失。 下面的实例显示了一个显式的类型转换: namespace TypeConversionApplication { class ExplicitConversion { static void Main(string
通过以上分析,我们可以看到强制类型转换在C语言编程中是一项非常实用的功能,它可以帮助开发者解决多种数据类型之间的转换问题。然而,在使用时也需注意潜在的问题,如数据损失和效率问题等。合理运用强制类型转换...
在使用KeilC51,一种专为8051微控制器设计的C语言编译器,进行软件开发时,数据类型的选择和转换是至关重要的。C51提供了丰富的数据类型,包括基本类型如int、char、float等,以及特定于8051的类型,如bit、sbit、...
类型转换可以分为两种:自动类型转换(隐式转换)和强制类型转换(显式转换)。 ### 二、自动类型转换 自动类型转换是指在无需程序员干预的情况下,编译器自动完成的数据类型转换。例如,在表达式计算中,如果涉及到...