当前位置: 首页 > 我的程序代码 > 正文

李迟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

/*===============================================*/

/* 素数 */

int prime(int num)

{

int i;

for (i=2; i<=num/2; i++)

if (num%i == 0)

return 0;

return 1;

}

void print_prime(int num)

{

int x =1;

while (x <= num)

{

if (prime(x))

printf(“%d “, x);

x += 1;

}

}
int main(void)

{

print_prime(999);

return 0;

}

#endif

#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 %dn”, ++t, t);

t = 5;

printf(“%d %dn”, t, ++t);

//printf(“%d %d %dn”, i++, ++i, i);

//printf(“%d %d %dn”, j, ++j, j++);

//ret = foo(i++, ++i, i);

ret = foo(j++, ++j, j);

printf(“%dn”, 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]=;

}

int main(void)

{

//char * org=”abcdabcdabcdefgabcd”; // 此处造成段错误

char org[] = “abcdabcdabcdefgabcd”;

printf(“Before:t%sn”,org);

SqueezeChar(org,‘c’);

printf(“After:t%sn”,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 %xn”, i, tmp);

printf(“%x %xn”, j, tmp1);

printf(“%x %xn”, k, tmp2);

printf(“%x %xn”, tmp3, tmp4);

printf(“%x %xn”, 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 %xn”, x, y, tmp, tmp1);

return 0;

}

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

* 二进制中1的个数 结束

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

#endif

本文所有代码片段可任意使用而不用告诉作者,当然,作者修改了也不必要告知阁下,而且,由于代码的错误而造成的损失亦与作者无关,不过一起讨论、学习还是可以的。

本文固定链接: http://www.latelee.org/my-library/code-for-march-2011.html

如无特别说明,迟思堂工作室文章均为原创,转载请注明: 李迟2011年3月代码积累 | 迟思堂工作室
【上一篇】

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter