2017-02-20 11:16:23 jiang1078 阅读数 345

需求:

输入整字节字符串,获取对应的16倍整字节数。即:输入字节在1-16之间,输出的字节数为16,17-32直接,输出为32

例如:

输入字节:000102030405,输出字节整数16.


C#代码

 int nOutputData = (strInputData.Length / 2+15)/16*16;

这仅仅是一个突发奇想,如果还有更简洁的方法,望指出。

2018-03-19 22:15:14 Super_Linux 阅读数 774

介绍一种高效的对整型数向上取整为2^n的倍数的方法。类似于下面的代码。

#define __ALIGN = 8

size_t RoundUp(size_t num){
  return ((num + (__ALIGN - 1)) & ~(__ALIGN));
}


返回的值便是对num向上取整为8的倍数。

2019-08-07 14:11:45 qq_40732350 阅读数 1815

计算向向上取整的

由于两数相除,默认是向下取整,而这里是向上取整数

#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))

参考:https://www.cnblogs.com/cmembd/p/3493597.html

计算向下取整的整数倍数

如:m = 5  n = 3,3的整数倍有3,6,9,12,但是对于5向下取整为3

解决:先用m/n得到商,然后再剩以n

#define DOWN_INT(M, N) (((M) / (N)) * (N))

计算向上取整的整数倍数

如:m = 5  n = 3,3的整数倍有3,6,9,12,但是对于5向上取整为6

解决:先用m/n得到商,然后(商+1)再剩以n

#define UP_INT(M, N) ((((M) + ((N) - 1)) / (N)) * (N))

当n为2的n次方时,改进上面的算法

其实这是Linux用来对指针做字节对齐的宏

#define ALIGN(x, a)           __ALIGN_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_MASK(x, mask) ( ((x) + (mask)) & ~(mask) )
#define PTR_ALIGN(p, a)       ((typeof(p))ALIGN((unsigned long)(p), (a)))

核心点在于a为  2^{N},所有  a - 1 再取反 后低位全为  0  高位全为1

举例:x = 5  a = 4(4   -->>    1111 1100)

由于高位不管是取0还是取1都是都是4的整数倍,如(8:0000 1000    16:0001 0000    24:0001 1000)

注意:a必须是 2^{N}

还有一个宏用于判断是否字节对齐

#define IS_ALIGNED(x, a)      ( ( (x) & ((typeof(x))(a) - 1) ) == 0)

参考:https://www.cnblogs.com/3me-linux/p/6026914.html

强制编译出错

#define BUILD_BUG_ON(e)         (sizeof(char[1 - 2 * !!(e)])    )
#define BUILD_BUG_ON_ZERO(e)    (sizeof(char[1 - 2 * !!(e)]) - 1)

 

注意核心表达式sizeof(char[1 - 2*!!(condition)])的作用,首先对条件表达式进行两次取反,这可以保证进行1 - 2*!!(condition)的结果只有两种值:条件为0时结果为1或者不为0则结果为-1,显然char[-1]将会导致编译器报错。注意:两次取反的目的是为了将表达式的值转换为逻辑值。

  • condition != 0:编译器报错
  • condition =  0:上面返回1   下面返回0

主要用在结构或其它自定义类型不满足指定大小就需要编译报错。

根据机构体成员地址找到结构体首地址

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({			\
	const typeof(((type *)0)->member) * __mptr = (ptr);	\
	(type *)((char *)__mptr - offsetof(type, member)); })

这个大家应该都很熟悉了,我这里就不说了

如果不懂可以参考我的这篇博客,有详细的解释:https://blog.csdn.net/qq_40732350/article/details/82960082

 

各个数据类型的最大值和最小值

#define USHRT_MAX	((u16)(~0U))
#define SHRT_MAX	((s16)(USHRT_MAX>>1))
#define SHRT_MIN	((s16)(-SHRT_MAX - 1))
#define INT_MAX		((int)(~0U>>1))
#define INT_MIN		(-INT_MAX - 1)
#define UINT_MAX	(~0U)
#define LONG_MAX	((long)(~0UL>>1))
#define LONG_MIN	(-LONG_MAX - 1)
#define ULONG_MAX	(~0UL)
#define LLONG_MAX	((long long)(~0ULL>>1))
#define LLONG_MIN	(-LLONG_MAX - 1)
#define ULLONG_MAX	(~0ULL)

va_list 、va_start、 va_arg、 va_end

当我们用可变参数来作为函数参数时,怎么一个一个的取得参数,如下

int DebugPrint(const char *pcFormat, ...) {

}

Glibc中有对应的宏,虽然这不是内核中的宏,但是还是可以拿来讲一下。

typedef char *va_list;

va_start宏,获取可变参数列表的第一个参数的地址(list是类型为va_list的指针,param1是可变参数最左边的参数):
#define va_start(list,param1)   ( list = (va_list)&param1+ sizeof(param1) )

va_arg宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(mode参数描述了当前参数的类型):
#define va_arg(list,mode)   ( (mode *) ( list += sizeof(mode) ) )[-1]

va_end宏,清空va_list可变参数列表:
#define va_end(list) ( list = (va_list)0 )

简单用法1

#include <stdio.h>
#include <stdarg.h>
void var_test(char *format, ...) {
    va_list list;
    va_start(list,format);   
    char *ch;
    while(1) {
         ch = va_arg(list, char *); //ch获得当前参数的地址,调用后,list指向下一个参数
         if(strcmp(ch,"") == 0) {    
               printf("\n");
               break;
         }
         printf("%s ",ch);
     }
     va_end(list);
}
int main() {
    var_test("test","this","is","a","test","");
    return 0;
}

简单用法2

#include<stdarg.h>
#include<stdio.h>
int sum(int num_args, ...) {
   int val = 0;
   va_list ap;
   int i;
   va_start(ap, num_args);
   for(i = 0; i < num_args; i++) {
      val += va_arg(ap, int);
   }
   va_end(ap);
   return val;
}
int main(void) {
   printf("10、20 和 30 的和 = %d\n",  sum(3, 10, 20, 30) );
   return 0;
}

简单用法3

int DebugPrint(const char *pcFormat, ...) {
	va_list tArg;
	/* 可变参数的处理, 抄自glibc的printf函数 */
	va_start (tArg, pcFormat);
	iNum = vsprintf (strTmpBuf, pcFormat, tArg);
	va_end (tArg);
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2012-08-08 16:17:28 cwq9944 阅读数 16417

floor函数

  floor(x),有时候也写做Floor(x),其功能是“下取整”,或者说“向下舍入”,即取不大于x的最大整数(与“四舍五入”不同,下取整是直接去掉小数部分),例如:
  x=3.14,floor(x)=3
  y=9.99999,floor(y)=9
  在C语言的库函数中,floor函数的语法如下:
  #include <math.h>
  double floor( double arg );
  功能: 函数返回参数不大于arg的最大整数。例如,
  x = 6.04;
  y = floor( x );
  y的值为6.0.
  与floor函数对应的是ceil函数,即上取整函数。
  有趣的是,floor在英文中是地板的意思,而ceil是天花板的意思,很形象地描述了下取整和上取整的数学运算。
  说明:如果任一参数为非数值参数,则 FLOOR 将返回错误值 #VALUE!。
  如果 number 和 significance 符号相反,则函数 FLOOR 将返回错误值 #NUM!。
  不论 number 的正负号如何,舍入时参数的绝对值都将减小。如果 number 恰好是 significance 的倍数,则无需进行任何舍入处理。
  FLOOR
  用途:将参数Number沿绝对值减小的方向去尾舍入,使其等于最接近的significance的倍数。
  语法:FLOOR(number,significance)
  参数:Number为要舍入的某一数值,Significance为该数值的倍数。
  实例:如果A1=22.5,则公式“=FLOOR(A1,1)”返回22;=FLOOR(-2.5,-2)返回-2。
  “使其等于最接近的significance的倍数”,比如:
  如果A1=22.5,则公式“=FLOOR(A1,1)“ 结果就是22,22最接近1的倍数
  如果A1=22.5,则公式“=FLOOR(A1,3)“ 结果就是21,21最接近3的倍数
  如果A1=25.8,则公式“=FLOOR(A1,3)“ 结果就是24,24最接近3的倍数

没有更多推荐了,返回首页