_INTSIZEOF(n)

转自:http://blog.csdn.net/sdcxyz/article/details/7067699

其实这个很简单。。不过位运算效率高点。 其实就是为了实现 (x+n-1)/n *n 的功能,(x+n-1)/n 与x/n比较显而易见就是保证商是不小于结果的最小整数.7/2 = 3(计算机中),但我们想要4 所以就需要(7+2-1)/2 = 4; 下面就是_INTSIZEOF(n)位运算的理解了


定义:

  #define _INTSIZEOF(n)  ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

1 我们知道对于IX86,sizeof(int)一定是4的整数倍,所以~(sizeof(int) - 1) )的值一定是 
右面[sizeof(n)-1]/2位为0,整个这个宏也就是保证了右面[sizeof(n)-1]/2位为0,其余位置 
为1,所以_INTSIZEOF(n)的值只有可能是4,8,16,......等等,实际上是实现了字节对齐。

2 #define _INTSIZEOF(n)  ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) 
的目的在于把sizeof(n)的结果变成至少是sizeof(int)的整倍数,这个一般用来在结构中实现按int的倍数对齐。 
如果sizeof(int)是4,那么,当sizeof(n)的结果在1~4之间是,_INTSIZEOF(n)的结果会是4;当sizeof(n)的结果在5~8时,

_INTSIZEOF(n)的结果会是8;当sizeof(n)的结果在9~12时,_INTSIZEOF(n)的结果会是12;……总之,会是sizeof(int)的倍数。

 

理论基础:

对于两个正整数 x, n 总存在整数 q, r 使得

x = nq + r, 其中  0<= r <n                  //最小非负剩余

q, r 是唯一确定的。q = [x/n], r = x - n[x/n]. 这个是带余除法的一个简单形式。在 c 语言中, q, r 容易计算出来: q = x/n, r = x % n.


所谓把 x 按 n 对齐指的是:若 r=0, 取 qn, 若 r>0, 取 (q+1)n. 这也相当于把 x 表示为:

x = nq + r', 其中 -n < r' <=0                //最大非正剩余   

nq 是我们所求。关键是如何用 c 语言计算它。由于我们能处理标准的带余除法,所以可以把这个式子转换成一个标准的带余除法,然后加以处理:

x+n = qn + (n+r'),其中 0<n+r'<=n            //最大正剩余

x+n-1 = qn + (n+r'-1), 其中 0<= n+r'-1 <n    //最小非负剩余

所以 qn = [(x+n-1)/n]n. 用 c 语言计算就是:

((x+n-1)/n)*n

若 n 是 2 的方幂, 比如 2^m,则除为右移 m 位,乘为左移 m 位。所以把 x+n-1 的最低 m 个二进制位清 0就可以了。得到:

(x+n-1) & (~(n-1))


<think>好的,我现在需要回答用户关于C语言中__builtin_va_list的宏定义和用途的问题。首先,我得回忆一下可变参数函数的相关知识。用户提到了几个引用,特别是引用[1]和引用[2],里面提到了va_start、va_end等宏,以及它们是如何通过内置函数或者手动实现的。 首先,__builtin_va_list应该是编译器内置的一个类型,用于处理可变参数列表。在C语言中,像printf这样的函数可以接受可变数量的参数,这就需要用到stdarg.h头文件中的va_list、va_start、va_arg、va_end这些宏和类型。不过,不同的编译器可能有不同的实现方式,像GCC就使用__builtin_va_list作为底层实现,而标准库中的va_list可能是它的别名。 然后,用户引用的内容中,引用[1]展示了使用__builtin_va_start和__builtin_va_end的宏定义,而引用[2]则是一个自定义的va_list实现,用了指针和地址运算。这说明不同环境下可能有不同的实现方式,但核心思想都是通过操作栈或寄存器来遍历可变参数。 接下来,我需要解释__builtin_va_list的用途。它主要用于声明一个指针,指向可变参数列表。然后通过va_start初始化这个指针,va_arg逐个获取参数,最后用va_end结束。用户提供的代码示例中的宏定义,比如va_start(ap,v)将ap指向第一个可变参数的位置,这通常是通过计算最后一个固定参数的地址加上其大小来实现的。 但需要注意的是,__builtin_va_list是编译器特定的实现,标准库的va_list可能在不同的编译器中有不同的定义。例如,GCC的内置函数可能更高效或处理不同架构的ABI差异。用户的问题可能涉及到为什么需要这些内置函数,以及它们和手动实现的区别。 可能还需要提到,使用这些内置函数的好处是编译器能更好地优化,并且处理不同平台的兼容性问题,比如参数的传递方式(栈传递 vs 寄存器传递),内存对齐等。例如,在x86和ARM架构下,可变参数的处理方式可能不同,内置函数会处理这些底层细节。 另外,引用[3]提到的_vsnprintf函数,其中使用了va_list参数,这说明在标准库函数中,可变参数的处理依赖于va_list类型和相关宏,而这些可能基于编译器内置的实现。 总结来说,__builtin_va_list是编译器提供的一个底层类型,用于实现可变参数函数,开发者通常通过stdarg.h中的宏来操作它,而无需直接使用内置名称,除非在特定的底层编程中。</think>### 解答 `__builtin_va_list` 是C语言编译器(如GCC)提供的内置类型,用于实现可变参数函数(例如 `printf`、`scanf`)。它是底层实现可变参数功能的关键组件,通常与 `va_start`、`va_arg`、`va_end` 等宏配合使用。 #### 1. **核心定义与用途** - **定义**:`__builtin_va_list` 是一个编译器内置的类型,表示可变参数列表的指针。在标准库 `<stdarg.h>` 中,`va_list` 通常定义为 `__builtin_va_list` 的别名[^1]。 - **用途**:用于声明一个指针,指向函数调用时传入的可变参数列表的起始位置。例如: ```c void my_printf(const char* format, ...) { __builtin_va_list args; va_start(args, format); // 初始化args,指向format后的第一个可变参数 // 通过va_arg(args, type)逐个提取参数 va_end(args); // 清理工作 } ``` #### 2. **底层原理** - **参数传递机制**:函数调用时,可变参数按特定规则(如栈传递或寄存器传递)存储。`__builtin_va_list` 通过编译器内置逻辑定位参数地址。 - **内存对齐**:宏 `_INTSIZEOF(n)` 计算类型 `n` 的内存对齐大小,确保正确偏移量[^2]。例如: ```c #define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1)) ``` #### 3. **操作宏的关联** - `va_start(ap, v)`:初始化 `ap`,使其指向第一个可变参数(`v` 是最后一个固定参数)。 - `va_arg(ap, t)`:从 `ap` 中提取类型为 `t` 的参数,并移动指针。 - `va_end(ap)`:清理 `ap`,防止内存泄漏[^1][^2]。 #### 4. **示例代码** ```c #include <stdarg.h> #include <stdio.h> void print_numbers(int count, ...) { va_list args; va_start(args, count); for (int i = 0; i < count; i++) { printf("%d ", va_arg(args, int)); } va_end(args); } int main() { print_numbers(3, 10, 20, 30); // 输出:10 20 30 return 0; } ``` #### 5. **注意事项** - **可移植性**:直接使用 `__builtin_va_list` 可能导致代码依赖特定编译器,建议优先使用标准库 `<stdarg.h>`。 - **类型安全**:`va_arg` 需明确指定参数类型,类型错误会导致未定义行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值