如何用一行代码初始化一个 sockaddr_in 结构体?

How to initialize a sockaddr_in struct with a single line of code?

使用C89/C99编译器,这两行代码可以工作

struct sockaddr_in server = { AF_INET, htons(27015), INADDR_ANY};
server.sin_addr.s_addr = inet_addr("127.0.0.1");

有更短的版本吗?例如,这些不起作用:

struct sockaddr_in server = { AF_INET, htons(27015), INADDR_ANY, inet_addr("127.0.0.1")};
struct sockaddr_in server = { AF_INET, htons(27015), INADDR_ANY, .sin_addr.s_addr = inet_addr("127.0.0.1") };

这个难看的长版本工作正常

struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(27015);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_addr.s_addr = inet_addr("127.0.0.1");

sockaddr_in 的格式为:

typedef struct sockaddr_in {
    short   sin_family;
    USHORT  sin_port;
    IN_ADDR sin_addr;
    CHAR    sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;

Windows 客户端

https://godbolt.org/z/8q8GPxP54

Windows 服务器

https://godbolt.org/z/8j3ozKKxP

此建议代码无法连接

struct sockaddr_in server = { AF_INET, htons(27015), {inet_addr("127.0.0.1")}, {0} };

此代码确实连接

struct sockaddr_in serverX;
serverX.sin_family = AF_INET;
serverX.sin_addr.s_addr = INADDR_ANY;
serverX.sin_port = htons(27015);
serverX.sin_addr.s_addr = inet_addr("127.0.0.1");

这是版本之间的区别。注意,服务器结构中的 s_addr 是 0x0000007f,而在 serverX:

中是 0x0100007f

两件事:首先,您将 sin_addr 的初始化器放错了地方。它是结构中的第三个元素,所以初始化器应该是第三个。其次,由于 sin_addr 是结构类型,因此您也需要将其初始化器放在大括号中。

所以你想要的是:

struct sockaddr_in server={ AF_INET, htons(27015), {inet_addr("127.0.0.1")}, {0}};

但是正如评论中提到的那样,将代码压缩到一行通常不是好的做法,因为它会使代码更难阅读。就个人而言,我更喜欢长版本,因为它让 reader 更清楚哪些字段正在用什么初始化。

另请注意,这仅适用于 .s_addr 字段定义为宏的系统,许多系统都是这样做的。例如,Windows(您似乎正在使用)定义 struct in_addr 如下:

struct in_addr {
        union {
                struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { u_short s_w1,s_w2; } S_un_w;
                u_long S_addr;
        } S_un;
#define s_addr  S_un.S_addr
                                /* can be used for most tcp & ip code */
#define s_host  S_un.S_un_b.s_b2
                                /* host on imp */
#define s_net   S_un.S_un_b.s_b1
                                /* network */
#define s_imp   S_un.S_un_w.s_w2
                                /* imp */
#define s_impno S_un.S_un_b.s_b4
                                /* imp # */
#define s_lh    S_un.S_un_b.s_b3
                                /* logical host */
};

许多较旧的 UNIX 发行版也是如此。

所以重申一下,使用对 reader 来说最清晰的代码,而不是适合一行的代码。