【问题标题】:What is the use of if condition followed by while(0)? [closed]if 条件后跟 while(0) 有什么用? [关闭]
【发布时间】:2016-10-20 00:22:46
【问题描述】:

我正在学习 C 中的 ping 源代码。

在此我被视为一行。即 if 条件后跟 while(0)

我在互联网上被搜索过。他们只给 line do 后跟 while(0) 。对于 do 后跟 while(0),我知道答案。但我不知道条件是否后跟 while(0)

示例代码是,

if (source.sin_addr.s_addr == 0) {
    socklen_t alen;
    struct sockaddr_in dst = whereto;
    int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);

    if (probe_fd < 0) {
        perror("socket");
        exit(2);
    }
    if (device) {
        struct ifreq ifr;
        int rc;

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, device, IFNAMSIZ-1);

        enable_capability_raw();
        rc = setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1);
        disable_capability_raw();

        if (rc == -1) {
            if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
                struct ip_mreqn imr;
                if (ioctl(probe_fd, SIOCGIFINDEX, &ifr) < 0) {
                    fprintf(stderr, "ping: unknown iface %s\n", device);
                    exit(2);
                }
                memset(&imr, 0, sizeof(imr));
                imr.imr_ifindex = ifr.ifr_ifindex;
                if (setsockopt(probe_fd, SOL_IP, IP_MULTICAST_IF, &imr, sizeof(imr)) == -1) {
                    perror("ping: IP_MULTICAST_IF");
                    exit(2);
                }
            } else {
                perror("ping: SO_BINDTODEVICE");
                exit(2);
            }
        }
    }

    if (settos &&
        setsockopt(probe_fd, IPPROTO_IP, IP_TOS, (char *)&settos, sizeof(int)) < 0)
        perror("Warning: error setting QOS sockopts");

    dst.sin_port = htons(1025);
    if (nroute)
        dst.sin_addr.s_addr = route[0];
    if (connect(probe_fd, (struct sockaddr*)&dst, sizeof(dst)) == -1) {
        if (errno == EACCES) {
            if (broadcast_pings == 0) {
                fprintf(stderr, "Do you want to ping broadcast? Then -b\n");
                exit(2);
            }
            fprintf(stderr, "WARNING: pinging broadcast address\n");
            if (setsockopt(probe_fd, SOL_SOCKET, SO_BROADCAST,
                       &broadcast_pings, sizeof(broadcast_pings)) < 0) {
                perror ("can't set broadcasting");
                exit(2);
            }
            if (connect(probe_fd, (struct sockaddr*)&dst, sizeof(dst)) == -1) {
                perror("connect");
                exit(2);
            }
        } else {
            perror("connect");
            exit(2);
        }
    }
    alen = sizeof(source);
    if (getsockname(probe_fd, (struct sockaddr*)&source, &alen) == -1) {
        perror("getsockname");
        exit(2);
    }
    source.sin_port = 0;

#ifndef WITHOUT_IFADDRS
    if (device) {
        struct ifaddrs *ifa0, *ifa;
        int ret;

        ret = getifaddrs(&ifa0);
        if (ret) {
            fprintf(stderr, "gatifaddrs() failed.\n");
            exit(2);
        }
        for (ifa = ifa0; ifa; ifa = ifa->ifa_next) {
            if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
                continue;
            if (!strncmp(ifa->ifa_name, device, sizeof(device) - 1) &&
                !memcmp(&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
                    &source.sin_addr, sizeof(source.sin_addr)))
                break;
        }
        freeifaddrs(ifa0);
        if (!ifa)
            fprintf(stderr, "ping: Warning: source address might be selected on device other than %s.\n", device);
    }
#endif
    close(probe_fd);
} while (0);

在 if 条件之后,他们使用 while(0)。这有什么用。

谁能解释一下。

【问题讨论】:

  • 对我来说看起来像是一个无害的错字。也许代码是一个 do/while 循环,有人将 do 更改为 if
  • 能发下源链接吗?
  • 也许可以稍微缩短一下上面的代码,用“…”标记遗漏的代码?就像现在一样,大部分代码与您的具体问题无关。
  • 这是来自 iputils 中的 ping.c。令人惊讶的是,代码审计没有发现这一点。它已经存在了至少 10 年。

标签: c linux ping


【解决方案1】:

你在阅读代码时欺骗了自己。

if (condition) {
    …
}

while (0)
    ;

这就是代码的真正含义。 while 循环完全没用(它什么也不做),我无法告诉你它可能存在的任何原因。

要解决这个问题,请让您的代码自动格式化。

【讨论】:

  • 这似乎不合理。
  • @hek2mgl:虽然这个答案缺乏推理,但它对代码的解释是正确的(我刚刚检查了源代码)。
  • @IgnacioVazquez-Abrams 我承认我没有检查代码,你说我这里的答案是错误的?
  • 不合理。在开源代码中,他们没有将任何行视为不合理。
  • @suresh:这有点……冒昧。开源绝不是完美的。
猜你喜欢
  • 2013-04-19
  • 1970-01-01
  • 2021-08-17
  • 2022-01-06
  • 2011-07-10
  • 2022-11-09
  • 2023-01-27
  • 1970-01-01
  • 2012-03-08
相关资源
最近更新 更多