李迟2011年3月代码积累

上个月积累的代码如下,由于在同一文件中测试多个代码段,因此只好用#if 0 ……#endif的形式来控制了。这次的代码包括:

1、测试函数入栈顺序,入栈顺序依据语言的不同而不同,C语言是从右到左的。从代码的运行结果也可以看出,因为栈帧是往下增长的。

2、从字符串中去除指定字符,这里在csdn帖子中抄来的,原问题是说出现了段错误,因为他使用的不是字符数组。详见代码。

3、移位操作,从http://aggregate.ee.engr.uky.edu/MAGIC/抄来的,上面有许多位运算的技巧。那个大小端转换是我自己临时加上去的,因为以前雄心勃勃想研究SD卡时候曾经写过,一时心血来潮也写一下,没想到还没忘记。

4、计算一个数的二进制中包含1的个数,比如7的二进制为0111,则1的个数为3。最后结果和3f相与,一开始不太理解,后来想通了,因为32位的二进制中1的个数最多是32个(似乎是废话)。那个求msb(搞过单片机的应该很熟悉这个东西)的函数中,结果是这样的:比如0x64,二进制为0x0110 0100,最高有效位为0x0100 0000,则结果为0x40。本文所有代码片段可任意使用而不用告诉作者,当然,作者修改了也不必要告知阁下,而且,由于代码的错误而造成的损失亦与作者无关,不过一起讨论、学习还是可以的。

 

 

/*************************************************


没有main函数
$ gcc rock.c -Wall
/usr/lib/gcc/i386-redhat-linux/4.3.0/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld 返回 1
**************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#if 0
/**************************************************
* 参数入栈测试
编译过程中出现警告:
$ gcc rock.c -Wall
rock.c: 在函数‘main’中:
rock.c:55: 警告:‘t’上的运算结果可能是未定义的
rock.c:57: 警告:‘t’上的运算结果可能是未定义的
rock.c:61: 警告:‘j’上的运算结果可能是未定义的
rock.c:61: 警告:‘j’上的运算结果可能是未定义的
rock.c:51: 警告:未使用的变量‘i’

测试结果:
$ ./a.out 
6 6
6 6
a=6[0xbfaeca30] b=7[0xbfaeca34] c=7[0xbfaeca38]
20
了解过堆栈帧的话,应该知道参数入栈的顺序
**************************************************/


int foo(int a, int b, int c)
{
        printf("a=%d[%p] ",a, &a);
        printf("b=%d[%p] ",b, &b);
        printf("c=%d[%p]/n",c, &c);
        return a+b+c;
}
int main(void)
{
        int i = 3;
        int j = 5;
        int ret;
        int t = 5;
        printf("%d %d/n", ++t, t);
        t = 5;
        printf("%d %d/n", t, ++t);
        //printf("%d %d %d/n", i++, ++i, i);
        //printf("%d %d %d/n", j, ++j, j++);
        //ret = foo(i++, ++i, i);
        ret = foo(j++, ++j, j);
        printf("%d/n", ret);
        return 0;
}
/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
* 参数入栈测试 结束
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

#endif

/*************************************************
* 字符串去除特定字符
* 段错误
运行结果:
$ ./a.out 
Before: abcdabcdabcdefgabcd
After:  abdabdabdefgabd
*************************************************/

#if 0
#include <string.h>
void SqueezeChar(char s[],int c)
{
        int i,j;
        for(i=j=0;i<strlen(s);i++)
                if(s[i]!=c)
                        s[j++]=s[i]; s[j]='/0';
}
int main(void)
{
        //char * org="abcdabcdabcdefgabcd"; // 此处造成段错误
        char org[] = "abcdabcdabcdefgabcd";
        printf("Before:/t%s/n",org);
        SqueezeChar(org,'c');
        printf("After:/t%s/n",org);

        return 0;
}
/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
* 字符串去除特定字符 结束
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

#endif

#if 0
/************************************************
8位、16位、32位平台无符号位反转,如0000ffff --> ffff0000
注:实际中需要注意位数需要一致。比如,不能将unsigned int版本的反转用于unsigned char中。
来自 http://aggregate.ee.engr.uky.edu/MAGIC/
运行结果:
$ ./a.out 
fffe 7fff0000
7f fe00
fe 7f
55aa8977 7789aa55
55aa aa55
*************************************************/

#include <stdio.h>

/* fe --> 7f */
unsigned char reverse8(register unsigned char x)
{
        x = (((x & 0xaa) >> 1) | ((x & 0x5555) << 1));
        x = (((x & 0xcc) >> 2) | ((x & 0x3333) << 2));

        return((x >> 4) | (x << 4));
}

/* 007f --> fe00 */
unsigned short reverse16(register unsigned short x)
{
        x = (((x & 0xaaaa) >> 1) | ((x & 0x5555) << 1));
        x = (((x & 0xcccc) >> 2) | ((x & 0x3333) << 2));
        x = (((x & 0xf0f0) >> 4) | ((x & 0x0f0f) << 4));

        return((x >> 8) | (x << 8));
}

/* fffe --> 7fff0000 */
unsigned int reverse32(register unsigned int x)
{
        x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
        x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
        x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
        x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));

        return((x >> 16) | (x << 16));
}

/* 大小端转换,如 55aa6788 --> 8867aa55 */
unsigned int endian_reverse32(register unsigned int x)
{
        return ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24);
}

/* 大小端转换, 如55aa --> aa55 */
unsigned short endian_reverse16(register unsigned short x)
{
        return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);
}

int main(void)
{
        unsigned int i = 65534;
        unsigned int tmp = reverse32(i);
        unsigned short j = 127;
        unsigned short tmp1 = reverse16(j);
        unsigned char k = 254;
        unsigned char tmp2 = reverse8(k);
        
        unsigned int tmp3 = 0x55aa8977;
        unsigned int tmp4 = endian_reverse32(tmp3);
        
        unsigned short tmp5 = 0x55aa;
        unsigned short tmp6 = endian_reverse16(tmp5);
        
        printf("%x %x/n", i, tmp);
        printf("%x %x/n", j, tmp1);
        printf("%x %x/n", k, tmp2);
        printf("%x %x/n", tmp3, tmp4);
        printf("%x %x/n", tmp5, tmp6);
        return 0;
}

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
* 位反转 结束
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

#endif

#if 0
/*************************************************
计算二进制中1的个数
运行结果:
$ ./a.out 
64 3 3 40
0x64 = 0110 0100 (共3个1)
0x40 = 0100 0000
*************************************************/


/* 计算一个数(32位无符号)的二进制中1的个数
 * 以x = 999测试,34条指令,占4个字节栈空间
 */

unsigned int binary_count(unsigned int x)
{
        unsigned int count = 0;
        while (x)
        {
                count++;
                //x = x&(x-1); /* 与 */
                x &= x-1;         /* 与 */
                #ifdef DEBUG
                printf("%x ", x);  /* debug */
                #endif
        }
        return count;
}

/* 另一个版本
 * 以x = 999测试,30条指令,不占栈空间
 * 最后一语句x & 0x0000003f, 因为32位1的个数最多只能是32位。
 */

unsigned int ones32(register unsigned int x)
{
         /* 32-bit recursive reduction using SWAR...
           but first step is mapping 2-bit values
           into sum of 2 1-bit values in sneaky way
        */

        x -= ((x >> 1) & 0x55555555);
        x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
        x = (((x >> 4) + x) & 0x0f0f0f0f);
        x += (x >> 8);
        x += (x >> 16);
        return(x & 0x0000003f);
}

/* 求一个数中的MSB */
unsigned int msb32(register unsigned int x)
{
        x |= (x >> 1);
        x |= (x >> 2);
        x |= (x >> 4);
        x |= (x >> 8);
        x |= (x >> 16);
        return(x & ~(x >> 1));
}

/* ?? */
unsigned int tzc(register int x)
{
        return(ones32((x & -x) - 1));
}

int main(void)
{
        unsigned int x = 100;
        unsigned int y = ones32(x);
        unsigned int tmp = binary_count(x);
        unsigned int tmp1 = msb32(x);
        printf("%x %x %x %x/n", x, y, tmp, tmp1);

        return 0;
}

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
* 二进制中1的个数 结束
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值