【问题标题】:I don't understand a macro of inet/netinet/in.h我看不懂inet/netinet/in.h 的宏
【发布时间】:2019-07-17 00:55:43
【问题描述】:

我正在使用 C 语言进行软件驱动程序的 IPv6 迁移,我想了解 IN6ADDR_ANY_INITIN6ADDR_LOOPBACK_INIT 的以下宏。请帮忙:

/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.
   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

#ifndef        _NETINET_IN_H
#define        _NETINET_IN_H        1
#include <features.h>
#include <bits/stdint-uintn.h>
#include <sys/socket.h>
#include <bits/types.h>

.
.
.

#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }

【问题讨论】:

  • 它可能被用作某些数组或结构的初始化器。只需将出现的宏名称替换为它的主体即可。
  • 您可以 grep 源代码树以在 .c 或其他 .h 文件中使用这些宏。 (我通常使用findxargsgrep,但我认为grep 也有一个-R 选项来递归grep 子目录。)
  • 这是一个 16 字节/128 位的初始化器,用于“任意”+“环回”地址。 32 位 IPv4 等效值为 #define INADDR_ANY ((unsigned long int) 0x00000000) + #define INPORT_ANY 0
  • 宏标识符的_INIT 部分是关于其预期用途的强烈信号:它们旨在用作初始化程序。此外,它们的特定句法形式在 C 中没有其他用途。特别是,它们是适用于 struct in6_addr 类型对象的初始化器(它们的标识符也强烈暗示了这一点)。

标签: c macros


【解决方案1】:

这些是struct in6_addr 的初始化器。 standard 要求 struct in6_addr 至少有一个成员 s6_addr,它必须是 uint8_t[16]

大多数时候,struct in6_addr 是作为嵌套联合实现的,其中包含 8、16 和 32 位整数数组以优化访问。例如,glibc 有

struct in6_addr {
  union {
    uint8_t __u6_addr8[16];
    uint16_t __u6_addr16[8];
    uint32_t __u6_addr32[4];
  } __in6_u;
};

和访问器定义

#define s6_addr                 __in6_u.__u6_addr8

请记住,联合初始化器需要它们自己的一组大括号并在联合的第一个成员上进行操作。结构体需要最外层的{},联合体需要下一层{},数组初始化器需要最内层的{}

因此

#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }

这是

0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 

#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }

这是

::1

【讨论】:

    【解决方案2】:

    The man page解释得很好。

    要将AF_INET6 套接字绑定到任何进程,本地地址应该 从具有in6_addr 类型的in6addr_any 变量复制。 在静态初始化中,也可以使用IN6ADDR_ANY_INIT, 它扩展为一个常量表达式。两人都在网络中 字节顺序。 IPv6 环回地址(::1) 在 全局in6addr_loopback 变量。对于初始化, 应该使用 IN6ADDR_LOOPBACK_INIT。可以使用 v4-mapped-on-v6 地址类型使用 v6 API 处理 IPv4 连接; 因此一个程序只需要支持这个 API 类型就可以同时支持 协议。这是由地址处理透明地处理的 C 库中的函数。

    【讨论】:

      猜你喜欢
      • 2014-02-18
      • 2020-09-11
      • 1970-01-01
      • 2021-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      相关资源
      最近更新 更多