为什么在WinSock2.h(c ++)中将无效套接字定义为〜0?

时间:2012-05-30 13:25:12

标签: c++ sockets network-programming

在WinSock2.h中,无效的套接字和套接字错误被定义为这些?这有什么意义吗?

#define INVALID_SOCKET  (SOCKET)(~0)
#define SOCKET_ERROR            (-1)

6 个答案:

答案 0 :(得分:31)

很久以前,在一个寒冷的雨天清晨,在华盛顿州西雅图一个古朴但不断发展的郊区,绿色覆盖的山丘中间,有一小片但又庞大的红砖建筑群,在一个其中一个是中型会议室,越来越多的网络软件工程师,经理和建筑师聚集在一起。会议已经开始悄悄地开始了,大多数男性组都喝着茶和咖啡,在他们的便笺上乱涂他们的机械铅笔,或者在他们的Palm Pilots上划伤(有那个的家伙与牛顿,但每个人都不理睬他。)

当演示者继续浏览源代码时,他被5位软件架构师中的一位拦截,这些架构师没有被邀请参加评审,但无论如何都出现了。 “什么,祈祷告诉,那个。”他说,像克林顿总统一样摇着他的手指。主持人停下来,盯着手指,发现自己被手指的摆动迷住了,因为建筑师继续摇摆。 “我说,”他开始重复。

主持人抬头看着屏幕,没有注意到任何不对劲。 “你在说什么?”他问道。

建筑师抬起眉毛,因为他的脸首先表示惊愕,然后转向愤怒,然后便秘,因为他大喊“是一种明显的编码风格指导违规!”。

观察者们开始互相窃窃私语,想知道问题究竟是什么。但是,主持人不知所措(第二种),很快就感谢您的反馈,并继续进行审查。

“我将被忽略!”,当他突然站起来时,建筑师尖叫着尖叫着,用一种懦弱的砰砰声将他的手掌猛地撞到桌面上。 / p>

当拳头敲打桌子时,房间爆发了,经理们开始设计掩盖他们背后的方法,工程师开始翻阅他们的编码风格手册,包括目录,索引,脚注和参考文献。

主持人在外面没有受到干扰,但感到很生气,因为他非常想要完成审查,以便他可以继续他的Snoqualmie滑雪之旅。 “你在谈论类型不匹配吗?”,他随口问道。

建筑师看了一会儿看起来很吃惊,但很快就重新组合了自己,“显然”,他哼了一声。

演示者用“〜0”替换了两个字符“-1”并转过身来。建筑师仔细检查了变化,然后是屏幕的其余部分,然后咨询了他的笔记,然后终于坐下来了。

其余的评论平安无事。

答案 1 :(得分:18)

在二进制补码系统上(Windows总是两个补码),~0等于-1,因此对编译器没有意义。

对读者可能有意义:~0强调它是一个设置了所有位的值,而-1强调它是一个小于0的值。

除了:

在不是二进制补码的系统上,假设SOCKET是无符号类型,编写(SOCKET)(~0)通常错误。原因是在这样的系统上,~0不代表值-1,它是INT_MIN,负零或陷阱表示之一。因此,它不一定会转换为类型SOCKET作为所有位为零的值,而是转换为INT_MAX+20或goodness-knows-what(也许是全部的值)位设置)。

因此,通常应使用-1初始化无符号类型,以获取设置了所有位的值。如果您知道要处理的是哪种无符号类型,可以使用UINT_MAX~0UL或类似内容。但这不值得,因为-1适用于所有无符号类型。

答案 2 :(得分:3)

主要是邋.. -1和~0实际上是一样的。

你可能会认为~0是更好的样式,因为socket是一个unsigned int,但实际上它对任何实际目的都没有任何影响。

因为他们使用“#define”而不是“const unsigned”,你仍然对陌生感持开放态度。 e.g。

    unsigned   a = SOCKET_ERROR;
    long long  b = a;
    if (b != SOCKET_ERROR)
        std::cout << "????\n";

可能会给一些人一个惊喜。

答案 3 :(得分:0)

因为SOCKET是无符号的,所以不能使用(-1)。

答案 4 :(得分:0)

INVALID_SOCKET用于返回SOCKET的函数,这是一个指针(很像HANDLE)。在32位系统上,它将是32位值,而在64位系统上,它将是64位值。

如果正确转换为等效大小的整数,则与-1相同。但是,如果不假设它将始终被正确演绎则更安全。

答案 5 :(得分:0)

每个(-1)是(~0)但不是每个(~0)都是(-1)。