1. Convert the byte array into an integer (Small End)
Interface:
# Define zenny_chenbytes2integer (buffer, length, type)
Buffer: const unsigned char * type, pointing to the starting address of the byte array
Length: size_t type, indicating the byte length of the array to be converted to an integer
Type: four types,
Zenny_chenbytes2integer_type_signed32 indicates a 32-bit signed integer, and INT is returned;
Zenny_chenbytes2integer_type_unsigned32 indicates an unsigned 32-bit integer, And the unsigned int is returned;
Zenny_chenbytes2integer_type_signed64 indicates a signed 64-bit integer, and long int is returned;
Zenny_chenbytes2integer_type_unsigned64 indicates an unsigned 64-bit integer, And the unsigned long int is returned.
The Code is as follows:
Function implementation:
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;}
The following are interfaces and test cases:
#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. Use stack switching to adapt to high-depth recursive function calls
In many cases, recursive algorithms are simple, elegant, and even faster. For example, the binary tree search algorithm obviously uses recursive forms much simpler than non-recursive ones, and in fact the execution efficiency is not worse than non-recursive forms. In this process, even if the node needs to be pushed into the stack in non-recursive form, and the stack operation is completely performed through software. The natural stack actually operates on the stack pointer register, so that its execution efficiency is more efficient than its own stack data structure.
However, the size of the user stack is usually dozens of KB. If the call depth is deep and the required stack size exceeds the maximum size of the user stack, an exception occurs during running. In this case, we can allocate a storage space and switch the current stack space to the storage space we allocated to solve this problem. The following sample code is a basic example of stack space switching:
/* * 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
The following is the source file:
/* ============================================================================ 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;}
The above code compilation runtime environment is: Lenovo z475 amd Apu A6-3420M, 4 GB ddr3, mingw GCC 4.6.2.
Note that in order to prevent the compiler from using the ESP register in a mixed manner, we recommend that you use one or more function calls when using your own storage space as the stack space, and function parameters are as few as possible.