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,如果調用深度較深,所需的棧大小超出使用者棧的最大大小,則會引發運行時異常。這個時候,我們可以通過自己分配一Block Storage空間,然後將當前棧空間切換到我們所分配的儲存空間來解決這個問題。下面的範例程式碼是棧空間切換的一個比較基本的例子:
/* * 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寄存器的混合使用,這裡推薦在使用自己開闢的儲存空間作為棧空間時,使用一個或一系列的函數調用,並且函數的參數盡量少。