当结构体遇上宏定义,以及函数指针的高级写法(结构体中能用宏定义一个函数?)

爷,独闯天下 提交于 2019-12-03 12:11:18
一、结构体中可以定义一般的宏定义
如:
 
struct aaa
{
   #define STATUS_1 100
   #define STATUS_2 200
   #define STATUS_3 300
   ........
};
   首先,这里的宏定义是在预编译阶段完成的,编译器此时并不知道什么结构体,所以这些宏是全局可见的。
   一个宏定义,如果写在结构体之内,即使与结构体之外的宏定义名字重复了最多是编译警告。可是如果不在结构体之内,名字重复可肯定是error。(未证实,可以做实验,而且可以把两处的宏定义成不同的值,会是什么情况?)
    定义在结构体之内的宏在结构体内可以隐藏定义在结构体之外定义的宏,如果都在结构体之外定义,那么就是定义了两个相同的宏,而一个在内,一个在外,则结构体内只看到内部定义的宏,而结构体外只看到外部定义的宏,跟变量的隐藏类似。
   宏的处理是在编译的预处理阶段完成的。预处理器根本就不认识什么结构体,在C语言编译器编译这个C文件中的结构体时,这个define语句已经不存在了。 相应的,用到这个宏的地方,宏本身也已经替换成宏的值(这个宏展开)。大家可以用gcc -E命令来只做预处理而不编译,看看出来后的文件。
至于为什么在结构体里头#deifne,是因为这个宏一般用于定义该结构体里头的标志位变量的可能的值,和结构体的这个变量密切相关。放在一起从逻辑上比较容易理解。
 
二、同理结构体中用宏定义一个类似于函数的东西(类似于C++内联函数)
如:
 
#define NETIF_INIT_SNMP(netif, type, speed) \
  /* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \
  netif->link_type = type;    \
  /* your link speed here (units: bits per second) */  \
  netif->link_speed = speed;  \
  netif->ts = 0;              \
  netif->ifinoctets = 0;      \
  netif->ifinucastpkts = 0;   \
  netif->ifinnucastpkts = 0;  \
  netif->ifindiscards = 0;    \
  netif->ifoutoctets = 0;     \
  netif->ifoutucastpkts = 0;  \
  netif->ifoutnucastpkts = 0; \
  netif->ifoutdiscards = 0
同之前所述,他只是一个宏,并不能作为结构体的成员变量,所以结构体中要使用函数,只能是吧函数指针作为成员变量。
 
 
三、结构体的高级写法(包含宏以及回调函数指针),出自STM32 LwIP,可以用来参考学习
 
struct netif {
  /** pointer to next in linked list */
  struct netif *next;
  /** IP address configuration in network byte order */
  struct ip_addr ip_addr;
  struct ip_addr netmask;
  struct ip_addr gw;
  /** This function is called by the network device driver
   *  to pass a packet up the TCP/IP stack. */
  err_t (* input)(struct pbuf *p, struct netif *inp);
  /** This function is called by the IP module when it wants
   *  to send a packet on the interface. This function typically
   *  first resolves the hardware address, then sends the packet. */
  err_t (* output)(struct netif *netif, struct pbuf *p,
       struct ip_addr *ipaddr);
  /** This function is called by the ARP module when it wants
   *  to send a packet on the interface. This function outputs
   *  the pbuf as-is on the link medium. */
  err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
#if LWIP_NETIF_STATUS_CALLBACK
  /** This function is called when the netif state is set to up or down
   */
  void (* status_callback)(struct netif *netif);
#endif /* LWIP_NETIF_STATUS_CALLBACK */
#if LWIP_NETIF_LINK_CALLBACK
  /** This function is called when the netif link is set to up or down
   */
  void (* link_callback)(struct netif *netif);
#endif /* LWIP_NETIF_LINK_CALLBACK */
  /** This field can be set by the device driver and could point
   *  to state information for the device. */
  void *state;
#if LWIP_DHCP
  /** the DHCP client state information for this netif */
  struct dhcp *dhcp;
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
  /** the AutoIP client state information for this netif */
  struct autoip *autoip;
#endif
#if LWIP_NETIF_HOSTNAME
  /* the hostname for this netif, NULL is a valid value */
  char*  hostname;
#endif /* LWIP_NETIF_HOSTNAME */
  /** number of bytes used in hwaddr */
  u8_t hwaddr_len;
  /** link level hardware address of this interface */
  u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
  /** maximum transfer unit (in bytes) */
  u16_t mtu;
  /** flags (see NETIF_FLAG_ above) */
  u8_t flags;
  /** descriptive abbreviation */
  char name[2];
  /** number of this interface */
  u8_t num;
#if LWIP_SNMP
  /** link type (from "snmp_ifType" enum from snmp.h) */
  u8_t link_type;
  /** (estimate) link speed */
  u32_t link_speed;
  /** timestamp at last change made (up/down) */
  u32_t ts;
  /** counters */
  u32_t ifinoctets;
  u32_t ifinucastpkts;
  u32_t ifinnucastpkts;
  u32_t ifindiscards;
  u32_t ifoutoctets;
  u32_t ifoutucastpkts;
  u32_t ifoutnucastpkts;
  u32_t ifoutdiscards;
#endif /* LWIP_SNMP */
#if LWIP_IGMP
  /* This function could be called to add or delete a entry in the multicast filter table of the ethernet MAC.*/
  err_t (*igmp_mac_filter)( struct netif *netif, struct ip_addr *group, u8_t action);
#endif /* LWIP_IGMP */
#if LWIP_NETIF_HWADDRHINT
  u8_t *addr_hint;
#endif /* LWIP_NETIF_HWADDRHINT */
#if ENABLE_LOOPBACK
  /* List of packets to be queued for ourselves. */
  struct pbuf *loop_first;
  struct pbuf *loop_last;
#if LWIP_LOOPBACK_MAX_PBUFS
  u16_t loop_cnt_current;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
#endif /* ENABLE_LOOPBACK */
};
————————————————
版权声明:本文为CSDN博主「练好基本功」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/nwd0729/article/details/50843750
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!