本人的C开源库——基于GNU11标准
1、将字节数组转为整型(小端)
接口为:
#define zenny_chenBYTES2INTEGER(buffer, length, type)
buffer:const unsigned char*类型,指向字节数组的起始地址
length:size_t类型,指示要转为整型的数组字节长度
type:四种类型,
zenny_chenBYTES2INTEGER_TYPE_SIGNED32表示32位带符号整型,最后返回int;
zenny_chenBYTES2INTEGER_TYPE_UNSIGNED32表示无符号32位整型,最后返回unsigned int;
zenny_chenBYTES2INTEGER_TYPE_SIGNED64表示带符号64位整型,最后返回long long int;
zenny_chenBYTES2INTEGER_TYPE_UNSIGNED64表示无符号64位整型,最后返回unsigned long long int
代码如下:
函数实现:
int ZennyChenBytes2SInteger(const unsigned char *pBuff, size_t length) { int value = 0; int shift = 0; for(size_t i = 0; i < length; i++) { int tmp = pBuff[i]; value += tmp << shift; shift += 8; } return value; } unsigned ZennyChenBytes2UInteger(const unsigned char *pBuff, size_t length) { unsigned value = 0; int shift = 0; for(size_t i = 0; i < length; i++) { unsigned tmp = pBuff[i]; value += tmp << shift; shift += 8; } return value; } long long ZennyChenBytes2SLong(const unsigned char *pBuff, size_t length) { long long value = 0; int shift = 0; for(size_t i = 0; i < length; i++) { long long tmp = pBuff[i]; value += tmp << shift; shift += 8; } return value; } unsigned long long ZennyChenBytes2ULong(const unsigned char *pBuff, size_t length) { unsigned long long value = 0; int shift = 0; for(size_t i = 0; i < length; i++) { unsigned long long tmp = pBuff[i]; value += tmp << shift; shift += 8; } return value; }
以下是接口以及测试用例
#define zenny_chenBYTES2INTEGER_TYPE_SIGNED32 int #define zenny_chenBYTES2INTEGER_TYPE_UNSIGNED32 unsigned int #define zenny_chenBYTES2INTEGER_TYPE_SIGNED64 long long int #define zenny_chenBYTES2INTEGER_TYPE_UNSIGNED64 unsigned long long int #define zenny_chenBYTES2INTEGER(buffer, length, type) _Generic((type)0, zenny_chenBYTES2INTEGER_TYPE_SIGNED32:ZennyChenBytes2SInteger, zenny_chenBYTES2INTEGER_TYPE_UNSIGNED32:ZennyChenBytes2UInteger, zenny_chenBYTES2INTEGER_TYPE_SIGNED64:ZennyChenBytes2SLong, zenny_chenBYTES2INTEGER_TYPE_UNSIGNED64:ZennyChenBytes2ULong, default:ZennyChenBytes2SLong)((buffer), (length)) int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... // int int si = -1; NSData *data = [NSData dataWithBytes:&si length:sizeof(si)]; unsigned char *buff = (unsigned char*)malloc([data length]); [data getBytes:buff length:[data length]]; NSLog(@"The value is: %d", zenny_chenBYTES2INTEGER(buff, [data length], zenny_chenBYTES2INTEGER_TYPE_SIGNED32)); free(buff); // unsigned unsigned ui = -1; data = [NSData dataWithBytes:&ui length:sizeof(ui)]; buff = (unsigned char*)malloc([data length]); [data getBytes:buff length:[data length]]; NSLog(@"The value is: %u", zenny_chenBYTES2INTEGER(buff, [data length], zenny_chenBYTES2INTEGER_TYPE_UNSIGNED32)); free(buff); // long long unsigned sll = 0x8888888888LL; data = [NSData dataWithBytes:&sll length:sizeof(sll)]; buff = (unsigned char*)malloc([data length]); [data getBytes:buff length:[data length]]; NSLog(@"The value is: 0x%.16llX", zenny_chenBYTES2INTEGER(buff, [data length], zenny_chenBYTES2INTEGER_TYPE_SIGNED64)); free(buff); // unsigned long long unsigned ull = 0x8888888888LL; data = [NSData dataWithBytes:&ull length:sizeof(ull)]; buff = (unsigned char*)malloc([data length]); [data getBytes:buff length:[data length]]; NSLog(@"The value is: 0x%.16llX", zenny_chenBYTES2INTEGER(buff, [data length], zenny_chenBYTES2INTEGER_TYPE_SIGNED64)); free(buff); } return 0; }
2、使用栈切换来适应高深度的递归函数调用
由于在很多情况下,使用递归形式使得算法既简洁,又优美,甚至执行速度更快。比如二叉树搜索这种算法,显然使用递归形式比非递归要简洁很多,而且事实上执行效率并不比非递归形式要差。由于这个过程中,即便用非递归形式仍然需要将节点压入栈中,而且这个栈操作完全是通过软件执行的。而天然的栈实际上就针对栈指针寄存器进行操作,从而使得其执行效率比自己做的栈数据结构来得高效。
然而一般用户栈的大小就几十KB,如果调用深度较深,所需的栈大小超出用户栈的最大大小,则会引发运行时异常。这个时候,我们可以通过自己分配一块存储空间,然后将当前栈空间切换到我们所分配的存储空间来解决这个问题。下面的示例代码是栈空间切换的一个比较基本的例子:
/* * zasm.asm * * Created on: 2013-1-13 * Author: Zenny Chen */ .text .align 2 .globl _Zenny_switch_stack, _Zenny_restore_stack // const void* Zenny_switch_stack(const void *pMem, size_t length); _Zenny_switch_stack: lea 4(%esp), %eax lea (%ecx, %edx, 1), %ecx mov (%esp), %edx mov %ecx, %esp push %edx ret // void Zenny_restore_stack(const void *pOrgStack); _Zenny_restore_stack: mov (%esp), %eax mov %ecx, %esp push %eax ret
下面是源文件:
/* ============================================================================ Name : recursionTest.c Author : Zenny Chen Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> extern const void* __fastcall Zenny_switch_stack(const void *pMem, size_t length); extern void __fastcall Zenny_restore_stack(const void *pOrgStack); static int RecursionSum(int n) { if(n == 0) return 0; else return n + RecursionSum(n - 1); } static int IterationSum(int n) { int sum = 0; for(int i = 0; i <= n; i++) sum += i; return sum; } static void DoRecursionTest(int *pResult) { int sum = RecursionSum(100000); *pResult = sum; } static void stack_swtich_test(void) { /** Outside the switch-stack region **/ void *pMem = malloc(4 * 1024 * 1024); int result; register int* const pResult = &result; const void *pOrgStack = Zenny_switch_stack(pMem, 4 * 1024 * 1024); /** Inside the switch-stack region **/ DoRecursionTest(pResult); Zenny_restore_stack(pOrgStack); /** Outside the switch-stack region **/ printf("The result is: %d\n", result); free(pMem); } int main(void) { puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */ stack_swtich_test(); printf("The sum result is: %d\n", IterationSum(100000)); return EXIT_SUCCESS; }
上述代码的编译运行环境为:Lenovo Z475 AMD APU A6-3420M,4GB DDR3,MinGW GCC 4.6.2。
这里要注意的是,为了防止编译器有时对esp寄存器的混合使用,这里推荐在使用自己开辟的存储空间作为栈空间时,使用一个或一系列的函数调用,并且函数的参数尽量少。