x&(x-1)表达式的意义 |
|
http://hi.baidu.com/zengzhaonong/blog/item/7fb884509ee30c61853524c2.html |
求下面函数的返回值(微软) -- 统计1的个数
-------------------------------------
int func(int x)
{
int countx = 0;
while(x)
{
countx++;
x = x&(x-1);
}
return countx;
}
假定x = 9999
10011100001111
答案: 8
思路: 将x转化为2进制,看含有的1的个数。
注: 每执行一次x = x&(x-1),会将x用二进制表示时最右边的一个1变为0,因为x-1将会将该位(x用二进制表示时最右边的一个1)变为0。
判断一个数(x)是否是2的n次方
-------------------------------------
#include <stdio.h>
int func(int x)
{
if( (x&(x-1)) == 0 )
return 1;
else
return 0;
}
int main()
{
int x = 8;
printf("%d\n", func(x));
}
注:
(1) 如果一个数是2的n次方,那么这个数用二进制表示时其最高位为1,其余位为0。
(2) == 优先级高于 &
|
字符串逆序(串中单个的单词不逆序) |
|
http://www.360doc.com/content/11/1024/23/1317564_158833674.shtml |
|
汇编语言课程设计——调试并修改一个小的内存驻留程序 |
|
http://www.4ngel.net/article/31.htm |
|
C语言宏定义使用技巧 |
|
http://blog.csdn.net/21aspnet/article/details/6724435 |
|
问题转载:javascript 的问题,在ie6中不能正常得到option 的值,FF中无问题,请大家帮帮我 |
|
javascript 的问题,在ie6中不能正常得到option 的值,FF中无问题,请大家帮帮我 |
|
【转载】分析一个好玩的c语言程序 |
|
【原创】分析一个好玩的c语言程序 |
前两天看到这么一个程序。代码如下:
#include <stdio.h>
int main()
{
const short int c1 = 49920;
const int c2 = 1073742008;
int (*pf)() = (int (*)())&c2;
printf("%c%c\n", *(char*)pf()-19, *((char*)pf()+1)-49);
return 0;
}
运行这个程序,屏幕上会出现一个 :)
很多人不懂其中的道理,在这里我给大家分析下代码。
先看这两句:
const short int c1 = 49920;
const int c2 = 1073742008;
定义了两个局部变量,数值转换成16进制为:
const short int c1 = 0xc300;
const int c2 = 0x400000b8;
其中变量c1的地址为:0x0012FF7C ,占两个字节,c2的地址为:0x0012FF78,占四个字节。这两个变量占据了连续的空间。变量赋值后,从0x12ff78开始的内存单元存储的字节码为:B8 00 00 40 00 C3 。对应的汇编码是:
mov eax,400000h
ret
接下来的这句:
int (*pf)() = (int (*)())&c2;
分析如下:
定义了一个函数指针,参数为NULL,返回值为int类型。 这个函数指针,指向上面的汇编码。这样,后面执行pf(),就执行了这段汇编码。
继续分析下面这句代码:
printf("%c%c\n", *(char*)pf()-19, *((char*)pf()+1)-49);
先看*(char*)pf()-19这个表达式, 执行了了pf指向的汇编代码,从汇编代码看,
这个函数调用后的返回值是0x400000,pf()前面的char *是把函数的返回值转换成一个
char*型指针,这个指针指向0x400000,前面再加个*号,表示取0x400000地址的内容,
由于是char *型指针,因此从这个地址取一个字节。
*(char*)pf()-19 表示的是从0x400000取出的字节内容再减去19。
接下来:*((char*)pf()+1)-49代表的意思是从0x400000 + 1的地址取出一个字节内容在减去49。
熟悉PE文件结构的朋友一定知道,对于exe文件0x400000是内存加载的基地址。
也就是说,0x400000 字节的内容对应的是0x4D,0x400001 字节的内容对应的是0x5A.
这是我们常说的pe文件起始的两个字节,"MZ"
这样,表达式*(char*)pf()-19的结果是0x3A ,表达式*((char*)pf()+1)-49的结果是0x29
察看ascii码表,输出就是我们看到的样子。
总结:
别看一个这么小的程序,但是其中涉及的知识面比较广。
|
PKU 1014多重背包问题 |
|
http://isomer.me/2011/03/pku-1014-dividing-1276-cash-machine-%E5%A4%9A%E9%87%8D%E8%83%8C%E5%8C%85/ |
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define max(a,b) (a>b)?a:b;
#define MAXV 20000*6+1
int dp[MAXV];
int nk[6];
int main(){
int i,k,min,v;
int cnt,sum;
int _case=0;
while(1){
for(sum=i=0;i<6;i++) { scanf("%d",&nk[i]); sum+=nk[i]*(i+1); }
if( !nk[0] & !nk[1] & !nk[2] & !nk[3] & !nk[4] & !nk[5] ) break;
_case++;
if( _case!=1 ) printf("\n");
if( sum%2 ) { printf("Collection #%d:\n",_case); printf("Can't be divided.\n"); }
else{
sum/=2;
memset(dp,0,sizeof(int)*(sum+1));
for(i=0;i<6;i++){
cnt=1;
k=(sum/(i+1)>=nk[i])?nk[i]:sum/(i+1);
while(k){
if( cnt>k ) cnt=k;
k-=cnt;
min=cnt*(i+1);
for(v=sum;v>=min;v--)
dp[v]=max(dp[v],dp[v-cnt*(i+1)]+cnt*(i+1));
cnt<<=1;
}
}
if( dp[sum] == sum ) { printf("Collection #%d:\n",_case); printf("Can be divided.\n");}
else { printf("Collection #%d:\n",_case); printf("Can't be divided.\n"); }
}
}
return 0;
}
|
输出自身 |
c 输出自身 |
http://hi.baidu.com/atyuwen/blog/item/318ceb9b688ea7b2c8eaf412.html |
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);}
|