本人的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寄存器的混合使用,这里推荐在使用自己开辟的存储空间作为栈空间时,使用一个或一系列的函数调用,并且函数的参数尽量少。

 

posted @ 2012-12-14 12:30  zenny_chen  Views(2143)  Comments(0Edit  收藏  举报