VS2005里面 _countof 的实现

本文深入解析了VS2005中_countof函数的实现原理,通过对比旧版定义,详细介绍了其C++版本的模板定义方式,并解释了其背后的数组指针、数组引用及模板推导等概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看一下VS2005里面_countof的定义(在stdlib.h里面):

/* _countof helper */

#if !defined(_countof)

#if !defined(__cplusplus)

#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))

#else

extern "C++"

{

template <typename _CountofType, size_t _SizeOfArray>

char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];

#define _countof(_Array) sizeof(*__countof_helper(_Array))

}

#endif

#endif

 

————————————————————华丽分割线————————————————————————

 

我们一步步的来对其进行解剖……

 

我们只看C++定义:

extern "C++"

{

template <typename _CountofType, size_t _SizeOfArray>

char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];

#define _countof(_Array) sizeof(*__countof_helper(_Array))

}

 

 ||

 ||

 //

 

看得有点费力,简化一下定义如下:

template <typename T, size_t size>

char (*__countof_helper(T (&_Array)[size]))[size];

#define _countof(_Array) sizeof(*__countof_helper(_Array))

 

 ||

 ||

 //

 

则对于

int Array[100];

 _countof(Array)

 

这样的代码进行宏展开为:

sizeof(*__countof_helper(Array))

 

__countof_helper不知道是啥,先放这里。

 

回头再看看那个模板,先回顾几个知识点:

知识点一:数组指针

char (* pArrayPtr)[size];

 

那么 pArrayPtr 就是一个指向包含 size 个元素的 char 数组的指针(注意那个小括号的作用,它影响了C++语法解析的优先级,如果没有小括号那么就是定义了一个普通的数组,数组中的每个成员都是一个char*):

 

再看 char (*__countof_helper( T ( &_Array)[size] ) )[size];(为了清楚,使用了颜色进行区分)

 

 ||

 ||

 //

 

看红色和绿色的部分,显然:__countof_helper(T (&_Array)[size]) 是一个函数声明,而其他部分则是该函数的返回类型,实际上就是返回一个指针数组。

而函数 __countof_helpe 参数是 T(&_Array)[size]

这里又有一个知识点,T(&_Array)[size] 是一个数组引用。知识点二:数组引用,这里参数使用数组引用就会保证传入的实际数组大小(size)和参数声明的数组大小是完全一致的。

 

 ||

 ||

 //

 

再看回 sizeof(*__countof_helper(Array))__countof_helper(Array)看似一个函数调用,但是实际上不会调用函数,而是直接进行编译期计算(sizeof是一个关键字,它直接在编译时计算传给它的表达式的类型的大小,没有运行时语义),此处会引发编译器模板推导,会推导出(根据int Array[100])函数原型:__countof_helper(int (&_Array)[100]) 返回值类型为:char (* pArrayPtr)[100],则sizeof(*__countof_helper(Array))里面对char (* pArrayPtr)[100]进行解引用再取sizeof的结果就是100(因为pArrayPtr就是一个指向100个元素的char数组指针,使用*解引用操作符之后就是一个100元素的char类型的数组)!!很犀利。

 

有几个问题:

1、微软为什么改成这样?而不用#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))这种直观的方式?有一点很重要是新方法能够进行参数类型检测了,非数组类型不能再传入_countof了,而之前是无法检查的。后来在网上看了老外的一篇文章,对这种方法的好处进行了描述,见http://blog.youkuaiyun.com/magictong/archive/2011/04/17/6329485.aspx

2、这里面涉及到哪些知识点……?数组指针,数组引用,模板?

 

u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) { struct hostapd_iface *iface = hapd->iface; struct hostapd_config *iconf = iface->conf; struct hostapd_hw_modes *mode = iface->current_mode; struct hostapd_channel_data *chan; int dfs, i; u8 channel, tx_pwr_count, local_pwr_constraint; int max_tx_power; u8 tx_pwr; if (!mode) return eid; if (ieee80211_freq_to_chan(iface->freq, &channel) == NUM_HOSTAPD_MODES) return eid; for (i = 0; i < mode->num_channels; i++) { if (mode->channels[i].freq == iface->freq) break; } if (i == mode->num_channels) return eid; switch (hostapd_get_oper_chwidth(iconf)) { case CHANWIDTH_USE_HT: if (iconf->secondary_channel == 0) { /* Max Transmit Power count = 0 (20 MHz) */ tx_pwr_count = 0; } else { /* Max Transmit Power count = 1 (20, 40 MHz) */ tx_pwr_count = 1; } break; case CHANWIDTH_80MHZ: /* Max Transmit Power count = 2 (20, 40, and 80 MHz) */ tx_pwr_count = 2; break; case CHANWIDTH_80P80MHZ: case CHANWIDTH_160MHZ: /* Max Transmit Power count = 3 (20, 40, 80, 160/80+80 MHz) */ tx_pwr_count = 3; break; default: return eid; } /* * Below local_pwr_constraint logic is referred from * hostapd_eid_pwr_constraint. * * Check if DFS is required by regulatory. */ dfs = hostapd_is_dfs_required(hapd->iface); if (dfs < 0) dfs = 0; /* * In order to meet regulations when TPC is not implemented using * a transmit power that is below the legal maximum (including any * mitigation factor) should help. In this case, indicate 3 dB below * maximum allowed transmit power. */ if (hapd->iconf->local_pwr_constraint == -1) local_pwr_constraint = (dfs == 0) ? 0 : 3; else local_pwr_constraint = hapd->iconf->local_pwr_constraint; /* * A STA that is not an AP shall use a transmit power less than or * equal to the local maximum transmit power level for the channel. * The local maximum transmit power can be calculated from the formula: * local max TX pwr = max TX pwr - local pwr constraint * Where max TX pwr is maximum transmit power level specified for * channel in Country element and local pwr constraint is specified * for channel in this Power Constraint element. */ chan = &mode->channels[i]; max_tx_power = chan->max_tx_power - local_pwr_constraint; /* * Local Maximum Transmit power is encoded as two's complement * with a 0.5 dB step. */ max_tx_power *= 2; /* in 0.5 dB steps */ if (max_tx_power > 127) { /* 63.5 has special meaning of 63.5 dBm or higher */ max_tx_power = 127; } if (max_tx_power < -128) max_tx_power = -128; if (max_tx_power < 0) tx_pwr = 0x80 + max_tx_power + 128; else tx_pwr = max_tx_power; *eid++ = WLAN_EID_TRANSMIT_POWER_ENVELOPE; *eid++ = 2 + tx_pwr_count; /* * Max Transmit Power count and * Max Transmit Power units = 0 (EIRP) */ *eid++ = tx_pwr_count; for (i = 0; i <= tx_pwr_count; i++) *eid++ = tx_pwr; return eid; }这个函数里面在哪设置的 Max Tx Pwr Unit Interpretation: Regulatory client EIRP (2)
最新发布
04-04
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值