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
<think>好的,我现在需要分析用户提供的C语言函数`hostapd_eid_txpower_envelope`,并回答其中在哪里设置了“Max Tx Pwr Unit Interpretation: Regulatory client EIRP (2)”这一参数。首先,我要理解这个函数的结构和作用,然后定位到相关代码部分。 首先,这个函数似乎用于构建某种无线网络管理帧中的传输功率包络信息元素(EID)。函数名中的`hostapd_eid_txpower_envelope`提示这是hostapd(一个用于无线接入点的守护进程)中生成EID的函数。EID是信息元素的缩写,通常在802.11帧中使用。 用户的问题是关于如何设置“Max Tx Pwr Unit Interpretation”为Regulatory client EIRP(值为2)。根据我的知识,EIRP(有效全向辐射功率)是无线设备发射功率的衡量标准,包括天线增益和线路损耗。在802.11标准中,传输功率相关的信息元素可能包含不同的单位解释,比如EIRP或不同的功率类型。 接下来,我需要查看函数中的代码,寻找与“Unit Interpretation”相关的部分。函数中有几处关键点: 1. 在设置EID的字段时,代码中有这样的行: ```c *eid++ = WLAN_EID_TRANSMIT_POWER_ENVELOPE; *eid++ = 2 + tx_pwr_count; *eid++ = tx_pwr_count; ``` 这里,前两个字节是EID和长度,第三个字节可能包含单位和计数信息。 根据802.11标准中的传输功率包络元素结构,第三个字节的结构可能分为两部分:低4位表示最大传输功率计数(Max Transmit Power Count),高4位表示单位解释(Max Transmit Power Unit Interpretation)。例如,如果高4位是0x2,那么单位解释是Regulatory client EIRP。 在代码中,第三字节被设置为`tx_pwr_count`,这里看起来可能有问题,因为`tx_pwr_count`的取值范围是根据信道宽度决定的,例如0、1、2、3。但根据标准,单位解释应该占据高4位,而计数在低4位。因此,正确的做法应该是将单位解释(比如2)左移4位,然后与tx_pwr_count进行或操作,组合成一个字节。 但当前代码中的第三字节直接赋值为`tx_pwr_count`,这似乎没有设置单位解释部分。这意味着可能代码中存在遗漏或者我的理解有误。或者,可能代码中的`tx_pwr_count`本身已经包含了单位解释的位? 仔细检查代码中的注释,发现这里有一个注释: ``` /* * Max Transmit Power count and * Max Transmit Power units = 0 (EIRP) */ *eid++ = tx_pwr_count; ``` 根据注释,这里将单位设置为0,即EIRP。但根据用户的问题,正确的值应该是2。这里可能存在矛盾。 但是,注释中提到“Max Transmit Power units = 0 (EIRP)”,这可能与实际情况不符。根据802.11标准,单位解释字段的值是: - 0: Regulatory Client EIRP - 1: Regulatory Client EIRP with DTPC - 2: Regulatory Client Transmit Power - 3: Regulatory Client Transmit Power with DTPC 所以,如果注释中的“0”表示单位是EIRP,那么实际代码中确实是将单位解释设置为0,而不是用户提到的2。但用户的问题中提到的值是2,这可能意味着用户的说法有误,或者代码版本不同。 回到代码,第三字节被赋值为`tx_pwr_count`,而根据注释,这里同时设置了计数和单位。然而,`tx_pwr_count`的值根据不同的信道宽度被设置为0、1、2、3,这显然只能占据低4位。而单位部分应该在高4位。例如,假设单位是0,那么整个字节应该是 (0 << 4) | tx_pwr_count。但代码中直接赋值,可能没有正确组合这两个部分,导致单位被错误地设置为0,而计数部分可能被截断。 这表明在当前的代码中,可能并没有正确设置单位解释为2,而是错误地设置为0。或者,可能注释有误,或者代码存在bug。 但用户的问题明确指出在哪里设置的值为2,这说明我可能哪里理解错了。需要重新审视代码。 另一种可能性是,代码中的第三字节中的高4位是单位,低4位是计数。例如,如果单位是2(二进制10),那么高4位是0010,而计数是tx_pwr_count(比如3,二进制0011),那么组合后的字节是00100011即0x23。但在代码中,第三字节直接赋值为tx_pwr_count,比如tx_pwr_count是3,那么第三字节是0x03,此时高4位是0,单位解释为0,而低4位是3,这显然与用户的问题不符。 因此,可能代码中存在错误,或者用户的问题有误。或者,可能我的理解有误,单位解释的字段位置或值不同。 再查阅标准文档,如IEEE 802.11-2020中的Transmit Power Envelope元素定义: Transmit Power Envelope元素的格式为: - Element ID: WLAN_EID_TRANSMIT_POWER_ENVELOPE (195) - Length: 1 + N - Transmit Power Information field: - Bits 0-3: Max Transmit Power Count (N-1) - Bits 4-7: Max Transmit Power Unit Interpretation - Followed by N octets of Max Transmit Power levels. 所以,第三个字节(Transmit Power Information字段)的高4位是Unit Interpretation,低4位是Count。Count的值等于Max Transmit Power Count +1,因为Count字段是N-1,其中N是后续的功率级别的数量。 在代码中: - `tx_pwr_count`是根据信道宽度设置的,例如,对于CHANWIDTH_USE_HT,当secondary_channel存在时,tx_pwr_count=1,对应的Count字段是1-1=0。而N的值是tx_pwr_count +1,即后续有2个功率级别?需要确认代码中的处理。 在代码中,第三字节被设置为`tx_pwr_count`,即: ```c *eid++ = tx_pwr_count; ``` 但是根据标准,第三字节的结构应该是(Unit << 4) | (Count),其中Count是Max Transmit Power Count = N-1,而N是后面的功率级别数目。 在代码中,后续循环填充了`tx_pwr_count +1`个功率级别: ```c for (i = 0; i <= tx_pwr_count; i++) *eid++ = tx_pwr; ``` 因此,长度字段是2 + tx_pwr_count,其中tx_pwr_count+1是功率级别的数目,所以长度应该是1(Transmit Power Info) + (tx_pwr_count +1),即2 + tx_pwr_count。 现在,问题在于Transmit Power Info字段的高四位是Unit Interpretation,而代码中第三字节直接赋值给tx_pwr_count,这显然只填充了低四位,而高四位没有被设置,导致Unit Interpretation默认为0,即Regulatory Client EIRP(0),而不是用户提到的2。 这说明在当前的函数中,并没有设置Unit Interpretation为2,而是设置为0。可能用户的疑问有误,或者代码中的注释与实际设置不一致。或者,可能Unit Interpretation的值0对应的是用户提到的Regulatory client EIRP,而用户将值2误解为其他情况。 根据标准中的定义,Max Transmit Power Unit Interpretation的值为: 0: EIRP 1: EIRP with DTPC 2: Transmit Power 3: Transmit Power with DTPC 因此,当代码中将Unit Interpretation设置为0时,对应的就是Regulatory client EIRP。而用户提到的值为2的情况对应的是“Transmit Power”,而非EIRP。所以,可能用户的问题中存在混淆,正确的情况是代码中设置的是0,即EIRP,而不是2。 查看代码中的注释: ``` /* * Max Transmit Power count and * Max Transmit Power units = 0 (EIRP) */ *eid++ = tx_pwr_count; ``` 注释明确说明单位被设置为0(EIRP),而`tx_pwr_count`是低四位。因此,正确的设置是Unit Interpretation为0,对应的EIRP,而用户提到的值为2的情况并未在此函数中设置。 因此,用户的问题可能存在误解,正确的答案是,该函数在第三字节的高四位将Unit Interpretation设置为0,对应Regulatory client EIRP,而不是2。因此,函数中并没有设置值为2的情况。可能用户参考的文档或标准中的值与实际代码不同,或者存在版本差异。</think>在函数`hostapd_eid_txpower_envelope`中,**Max Tx Pwr Unit Interpretation: Regulatory client EIRP** 的设置是通过以下代码实现的: ```c /* * Max Transmit Power count and * Max Transmit Power units = 0 (EIRP) */ *eid++ = tx_pwr_count; ``` ### 关键点解析: 1. **字段结构** 传输功率包络元素的第三个字节(Transmit Power Information)包含两个部分: - **高4位**:`Max Tx Pwr Unit Interpretation`(单位解释) - **低4位**:`Max Tx Pwr Count`(功率层级数量) 2. **代码逻辑** 代码中通过注释明确说明: ```c /* * Max Transmit Power count and * Max Transmit Power units = 0 (EIRP) */ *eid++ = tx_pwr_count; ``` - `tx_pwr_count` 仅占用低4位,表示支持的功率层级数量(例如:`0` 表示1个层级,`1` 表示2个层级等)。 - **高4位未显式赋值**,但注释表明单位解释被硬编码为 `0`(即 `Regulatory client EIRP`)。 3. **值与含义** 根据IEEE 802.11标准: - `0`: Regulatory Client EIRP(有效全向辐射功率) - `1`: Regulatory Client EIRP with DTPC(动态传输功率控制) - `2`: Regulatory Client Transmit Power(实际发射功率) - `3`: Regulatory Client Transmit Power with DTPC **因此,函数中设置的 `0` 对应 `EIRP`,而非值 `2`。** ### 为何用户可能误解? 用户提到的值 `2` 可能混淆了以下两种场景: 1. **EIRP(代码中为 `0`)** 表示功率包含天线增益和损耗,是监管要求的常用单位。 2. **Transmit Power(值为 `2`)** 表示仅设备自身的发射功率(不含天线增益),但函数中未采用此选项。 ### 总结 函数通过隐式赋值 `*eid++ = tx_pwr_count` 将 **高4位设为 `0`**(即 `EIRP`),低4位设为 `tx_pwr_count`。若需改为 `Regulatory client Transmit Power`(值 `2`),需显式合并高4位和低4位,例如: ```c *eid++ = (2 << 4) | tx_pwr_count; // 高4位=2,低4位=tx_pwr_count ``` 但当前实现未采用此逻辑。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值