如何用一行代码初始化一个 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 来说最清晰的代码,而不是适合一行的代码。
使用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 来说最清晰的代码,而不是适合一行的代码。