6.12

来源:互联网 发布:无限鼠标 知乎 编辑:程序博客网 时间:2024/05/22 12:47

4.
for(i=0;i<n;)
{
 if(a[a[i]]!=a[i])
 {                                
temp=a[a[i]];                     
a[a[i]]=a[i];                     
a[i]= temp;
for(j=0;j<n;j++)
printf("%d ",a[j]);
printf("/t i=%d/n",i);}

else
i++;   
}


5.
两个乒乓球队进行比赛,各出3个人。甲对为a、b、c3人,乙对x、y、z3人。已经抽签决定比赛名单。有人向队员打听比赛名单。a说他不和x比,c说他不和x、z比,请编程找出3队赛手的名单?
# include "stdio.h"
main()
{
int a=1,b=2,c=3,x,y,z;
for(x=1;x<4;x++)
    for(y=1;y<4;y++)
        for(z=1;z<4;z++)
            if(x!=1&&z!=3&&x!=3&&x!=y&&x!=z&&y!=z)
                printf("/n%d%d%d/n",x,y,z);
                    getch();
}

6.
  一个32位的机器,该机器的指针是多少位
32位机器的地址总线是32位,所以内存单元的地址是32位的, 指针存放地址, 所以指针也就是32位的

7.
m能被a整除,m除以b余c,m, a, b, c都是正整数,求最小的m关于a, b, c的表达式

#include "stdio.h"
main()
{
int m,i,t=0;
for(m=1;m<=100;m++)
    {
        for(i=1;i<m;i++)
            if(m%i==0&&m%(i+1)!=0)
                {t=1;break;}
                if(t)
                break;
    }
    printf("/n m=%d a=%d  b=%d  c=%d",m,i,i+1,m%(i+1));
getch();

}

8.想问问关于CRC32的问题

我想获得一个字符串的CRC32校验码,在网上找了4个函数,但是所得到的校验码都不一样,不知道哪个是正确的.下面给出码表和这四个函数的代码,请指教~~
码表:
static unsigned long crc32_tab[] = {
      0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
      0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
      0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
      0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
      0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
      0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
      0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
      0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
      0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
      0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
      0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
      0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
      0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
      0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
      0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
      0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
      0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
      0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
      0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
      0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
      0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
      0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
      0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
      0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
      0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
      0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
      0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
      0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
      0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
      0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
      0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
      0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
      0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
      0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
      0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
      0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
      0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
      0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
      0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
      0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
      0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
      0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
      0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
      0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
      0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
      0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
      0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
      0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
      0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
      0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
      0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
      0x2d02ef8dL
   };
函数一:
unsigned long crc32(const unsigned char *s, unsigned int len)
{
  unsigned int i;
  unsigned long crc32val;
 
  crc32val = 0;
  for (i = 0;  i < len;  i ++)
    {
      crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
    }
  return crc32val;
}
函数二:
unsigned long GenerateCRC32(char  * DataBuf,unsigned long  len)
{
    unsigned long oldcrc32;
    unsigned long crc32;
    unsigned long oldcrc;
    unsigned  int charcnt;
    char c, t;

    oldcrc32 = 0x00000000; //初值为0
    charcnt=0;
    while (len--)
    {
        t= (oldcrc32 >> 24) & 0xFF;   //要移出的字节的值
        oldcrc=crc32_tab[t];         //根据移出的字节的值查表
        c=DataBuf[charcnt];          //新移进来的字节值
        oldcrc32= (oldcrc32 << 8) | c;   //将新移进来的字节值添在寄存器末字节中
        oldcrc32=oldcrc32^oldcrc;     //将寄存器与查出的值进行xor运算
        charcnt++;
    }
    crc32=oldcrc32;
    return crc32;
}
函数三:
unsigned long calculateCRC(void *pMem,unsigned int byteSize)
{
    unsigned int i;
long m_CRC = 0xffffffff;
    char *pD;
    pD=(char *) pMem;
    for(i=0;i<byteSize;i++)
        m_CRC=crc32_tab[(m_CRC^(*(pD+i)))&0xff] ^ (m_CRC>>8);
    return m_CRC;
}
函数四:
unsigned long CRC32(unsigned char * databuf,unsigned long len)
{
unsigned long temp;
unsigned long oldcrc=0xffffffff;
while(len--)
{
temp = (oldcrc ^(*databuf )) & 0x000000FF;
oldcrc = (( oldcrc >> 8) & 0x00FFFFFF) ^ crc32_tab[temp];
}
return ~oldcrc;
}

 

// CRC校验模板
template < typename _Type, unsigned long _CRC_VAL >
class CCRC_T {
 static _Type *GetCRCTable( void ) {
  static _Type _CRC_TABLE[256];
  return _CRC_TABLE;
 }
public:
 // 计算CRC (一般算法)
 static _Type Cal( const void * pData, unsigned long nLen, _Type nLastCRC = 0 ) {
  _Type nResult = nLastCRC;
  unsigned char &cTopResultByte = *( (unsigned char *)&nResult + ( sizeof(_Type) - 1 ) );
  
  while ( nLen-- > 0 ) {
   unsigned char cTopDataByte = *(unsigned char *)pData;
   pData = ((unsigned char *)pData) + 1;
   for( long i = 0; i<8; i++ ) {
    if ( (cTopDataByte&0x80) != (cTopResultByte&0x80) ) {
     nResult <<= 1;
     nResult ^= _CRC_VAL;
    } else {
     nResult <<= 1;
    }
    cTopDataByte <<= 1;
   }
  }
  return nResult;
 }
 // 快速算法初始化
 static void InitFastCal( void ) {
  _Type *pTable = GetCRCTable();
  unsigned long cTmp = 0;
  for( ; cTmp<=0xFF; cTmp++ ) {
   pTable[cTmp] = Cal( &cTmp, 1 );
  }
  pTable[cTmp] = Cal( &cTmp, 1 );
 }
 // 计算CRC (快速算法)
 static _Type FastCal( const void * pData, unsigned long nLen, _Type nLastCRC = 0 ) {
  _Type *pTable = GetCRCTable();
  _Type nResult = nLastCRC;
  while ( nLen-- > 0 ) {
   unsigned char cTopDataByte = *(unsigned char *)pData;
   pData = ((unsigned char *)pData) + 1;
   unsigned char cTopResultByte = *( (unsigned char *)&nResult + ( sizeof(_Type) - 1 ) );
   nResult <<= 8;
   nResult ^= pTable[cTopResultByte^cTopDataByte];
  }
  return nResult;
  }
};
 
typedef CCRC_T< unsigned short, 0x1005 > CRC16;
typedef CCRC_T< unsigned short, 0x1021 > CRCITU;
typedef CCRC_T< unsigned long, 0x04C11DB7 > CRC32;
typedef CCRC_T< unsigned long, 0x1EDC6F41 > CRC32c;


9.linux 下汇编
书名:汇编语言程序设计
定价:¥48
【原书名】 Professional Assembly Language [原书信息] 
【原出版社】 John Wiley & Sons 
【作者】 (美)Richard Blum 
【译者】 马朝晖 等 
【出版社】 机械工业出版社  【书号】 7-111-17532-8
【开本】 16开 【页码】 409
【出版日期】 2006-1-1  【版次】 1-1 

当时我在图书馆看到这本书的时候,二话不说就借出来了,理由很简单,我以前一直没看过专门讲AT&T汇编语法的书。后来拿回来仔细看了之后,才知道书名:汇编语言程序设计确实委屈了这本书,因为这本书里面所讲的内容远远超过了我们平时国内出的一些所谓的汇编语言程序设计。关键是这本书也容易读懂。我花了20天就把这本书看完第一遍了,大概的时间安排是:每天早上8点到8点半开始复习前一天的笔记,然后到11点半就看新内容,我是一天看一章的(20来页)。晚上做实验1~2小时。
意外收获:
1、书中的许多例子都用as/ld编译,用gdb调试,这样就学到的额外的调试的知识。如果你照书里的实验做下来,你就不算调试高手,也会对GDB调试很熟练的。
2、教我们怎么创建静态库、动态库。以前一直对动态库感觉很遥远,看完了里面的讲述,就很清楚动态库到底是什么了,没什么神秘的了。
3、以前看汇编的时候,总是对浮点寄存器很烦。看这本书之后,发现浮点计算也是挺简单的,还很亲切。
4、一直不知道MMX、SSE、SSE2、SSE3技术是些什么东东。呵呵,其实也没什么
5、里面对指令的细节也讲得不错,以前会经常犯的一些错误,里面也提到了一些。

如果你也觉得这本书好,就帮忙顶一下,让其它人也能看到。
另外如果大家在书中遇上一些问题,可以到我的QQ群(21964639)里来找我,请注明pal(即Professional Assembly Language )

 

10。
这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将会学到以下内容:

源程序编译

Makefile的编写

程序库的链接

程序的调试

头文件和系统求助


1.源程序的编译

在Linux下面,如果要编译一个C语言源程序,我们要使用GNU的gcc编译器. 下面我们以一个实例来说明如何使用gcc编译器.

假设我们有下面一个非常简单的源程序(hello.c):


int main(int argc,char **argv)
{
printf(""Hello Linux "");
}
 

要编译这个程序,我们只要在命令行下执行:

gcc -o hello hello.c

gcc 编译器就会为我们生成一个hello的可执行文件.执行./hello就可以看到程序的输出结果了.命令行中 gcc表示我们是用gcc来编译我们的源程序,-o 选项表示我们要求编译器给我们输出的可执行文件名为hello 而hello.c是我们的源程序文件.

gcc编译器有许多选项,一般来说我们只要知道其中的几个就够了. -o选项我们已经知道了,表示我们要求输出的可执行文件名. -c选项表示我们只要求编译器输出目标代码,而不必要输出可执行文件. -g选项表示我们要求编译器在编译的时候提供我们以后对程序进行调试的信息.

知道了这三个选项,我们就可以编译我们自己所写的简单的源程序了,如果你想要知道更多的选项,可以查看gcc的帮助文档,那里有着许多对其它选项的详细说明.

2.Makefile的编写

假设我们有下面这样的一个程序,源代码如下:


/* main.c */
#include ""mytool1.h""
#include ""mytool2.h""
int main(int argc,char **argv)
{
mytool1_print(""hello"");
mytool2_print(""hello"");
}
/* mytool1.h */
#ifndef _MYTOOL_1_H
#define _MYTOOL_1_H
void mytool1_print(char *print_str);
#endif
/* mytool1.c */
#include ""mytool1.h""
void mytool1_print(char *print_str)
{
printf(""This is mytool1 print %s "",print_str);
}
/* mytool2.h */
#ifndef _MYTOOL_2_H
#define _MYTOOL_2_H
void mytool2_print(char *print_str);
#endif
/* mytool2.c */
#include ""mytool2.h""
void mytool2_print(char *print_str)
{
printf(""This is mytool2 print %s "",print_str);
}
 

当然由于这个程序是很短的我们可以这样来编译

gcc -c main.c

gcc -c mytool1.c

gcc -c mytool2.c

gcc -o main main.o mytool1.o mytool2.o

这样的话我们也可以产生main程序,而且也不时很麻烦.但是如果我们考虑一下如果有一天我们修改了其中的一个文件(比如说mytool1.c)那么我们难道还要重新输入上面的命令?也许你会说,这个很容易解决啊,我写一个SHELL脚本,让她帮我去完成不就可以了.是的对于这个程序来说,是可以起到作用的.但是当我们把事情想的更复杂一点,如果我们的程序有几百个源程序的时候,难道也要编译器重新一个一个的去编译?

为此,聪明的程序员们想出了一个很好的工具来做这件事情,这就是make.我们只要执行以下make,就可以把上面的问题解决掉.在我们执行make之前,我们要先编写一个非常重要的文件.Makefile.对于上面的那个程序来说,可能的一个Makefile的文件是:

# 这是上面那个程序的Makefile文件

main:main.o mytool1.o mytool2.o

gcc -o main main.o mytool1.o mytool2.o

main.o:main.c mytool1.h mytool2.h

gcc -c main.c

mytool1.o:mytool1.c mytool1.h

gcc -c mytool1.c

mytool2.o:mytool2.c mytool2.h

gcc -c mytool2.c

有了这个Makefile文件,不过我们什么时候修改了源程序当中的什么文件,我们只要执行make命令,我们的编译器都只会去编译和我们修改的文件有关的文件,其它的文件她连理都不想去理的.

下面我们学习Makefile是如何编写的.

在Makefile中也#开始的行都是注释行.Makefile中最重要的是描述文件的依赖关系的说明.一般的格式是:

target: components

TAB rule

第一行表示的是依赖关系.第二行是规则.

比如说我们上面的那个Makefile文件的第二行

main:main.o mytool1.o mytool2.o

表示我们的目标(target)main的依赖对象(components)是main.o mytool1.o mytool2.o 当倚赖的对象在目标修改后修改的话,就要去执行规则一行所指定的命令.就象我们的上面那个Makefile第三行所说的一样要执行 gcc -o main main.o mytool1.o mytool2.o 注意规则一行中的TAB表示那里是一个TAB键

Makefile有三个非常有用的变量.分别是$@,$^,$<代表的意义分别是:

$@目标文件,$^所有的依赖文件,$<第一个依赖文件.

如果我们使用上面三个变量,那么我们可以简化我们的Makefile文件为:

# 这是简化后的Makefile

main:main.o mytool1.o mytool2.o

gcc -o $@ $^

main.o:main.c mytool1.h mytool2.h

gcc -c $<

mytool1.o:mytool1.c mytool1.h

gcc -c $<

mytool2.o:mytool2.c mytool2.h

gcc -c $<

经过简化后我们的Makefile是简单了一点,不过人们有时候还想简单一点.这里我们学习一个Makefile的缺省规则

.c.o:

gcc -c $<

这个规则表示所有的 .o文件都是依赖与相应的.c文件的.例如mytool.o依赖于mytool.c这样Makefile还可以变为:

# 这是再一次简化后的Makefile

main:main.o mytool1.o mytool2.o

gcc -o $@ $^

.c.o:

gcc -c $<

好了,我们的Makefile 也差不多了,如果想知道更多的关于Makefile规则可以查看相应的文档.

3.程序库的链接

试着编译下面这个程序

/* temp.c */

#include

int main(int argc,char **argv)

{

double value;

printf(""Value:%f "",value);

}

这个程序相当简单,但是当我们用 gcc -o temp temp.c 编译时会出现下面所示的错误.

/tmp/cc33Kydu.o: In function ``main&acute;&acute;:

/tmp/cc33Kydu.o(.text+0xe): undefined reference to ``log&acute;&acute;

collect2: ld returned 1 exit status

出现这个错误是因为编译器找不到log的具体实现.虽然我们包括了正确的头文件,但是我们在编译的时候还是要连接确定的库.在Linux下,为了使用数学函数,我们必须和数学库连接,为此我们要加入 -lm 选项. gcc -o temp temp.c -lm这样才能够正确的编译.也许有人要问,前面我们用printf函数的时候怎么没有连接库呢?是这样的,对于一些常用的函数的实现,gcc编译器会自动去连接一些常用库,这样我们就没有必要自己去指定了. 有时候我们在编译程序的时候还要指定库的路径,这个时候我们要用到编译器的 -L选项指定路径.比如说我们有一个库在 /home/hoyt/mylib下,这样我们编译的时候还要加上 -L/home/hoyt/mylib.对于一些标准库来说,我们没有必要指出路径.只要它们在起缺省库的路径下就可以了.系统的缺省库的路径/lib /usr/lib /usr/local/lib 在这三个路径下面的库,我们可以不指定路径.

还有一个问题,有时候我们使用了某个函数,但是我们不知道库的名字,这个时候怎么办呢?很抱歉,对于这个问题我也不知道答案,我只有一个傻办法.首先,我到标准库路径下面去找看看有没有和我用的函数相关的库,我就这样找到了线程(thread)函数的库文件(libpthread.a). 当然,如果找不到,只有一个笨方法.比如我要找sin这个函数所在的库. 就只好用 nm -o /lib/*.so|grep sin>~/sin 命令,然后看~/sin文件,到那里面去找了. 在sin文件当中,我会找到这样的一行libm-2.1.2.so:00009fa0 W sin 这样我就知道了sin在 libm-2.1.2.so库里面,我用 -lm选项就可以了(去掉前面的lib和后面的版本标志,就剩下m了所以是 -lm). 如果你知道怎么找,请赶快告诉我,我回非常感激的.谢谢!

4.程序的调试

我们编写的程序不太可能一次性就会成功的,在我们的程序当中,会出现许许多多我们想不到的错误,这个时候我们就要对我们的程序进行调试了.

最常用的调试软件是gdb.如果你想在图形界面下调试程序,那么你现在可以选择xxgdb.记得要在编译的时候加入 -g选项.关于gdb的使用可以看gdb的帮助文件.由于我没有用过这个软件,所以我也不能够说出如何使用. 不过我不喜欢用gdb.跟踪一个程序是很烦的事情,我一般用在程序当中输出中间变量的值来调试程序的.当然你可以选择自己的办法,没有必要去学别人的.现在有了许多IDE环境,里面已经自己带了调试器了.你可以选择几个试一试找出自己喜欢的一个用.

5.头文件和系统求助

有时候我们只知道一个函数的大概形式,不记得确切的表达式,或者是不记得着函数在那个头文件进行了说明.这个时候我们可以求助系统.

比如说我们想知道fread这个函数的确切形式,我们只要执行 man fread 系统就会输出着函数的详细解释的.和这个函数所在的头文件说明了. 如果我们要write这个函数的说明,当我们执行man write时,输出的结果却不是我们所需要的. 因为我们要的是write这个函数的说明,可是出来的却是write这个命令的说明.为了得到write的函数说明我们要用 man 2 write. 2表示我们用的write这个函数是系统调用函数,还有一个我们常用的是3表示函数是C的库函数。

记住不管什么时候,man都是我们的最好助手。

好了,这一章就讲这么多了,有了这些知识我们就可以进入激动人心的Linux下的C程序探险活动。

 

 

原创粉丝点击