原创 C语言知识

2009-3-16 09:25 2426 5 5 分类: 工程师职场

char  *string ="i  love  china"


等价于:


 char  *string;


 string="i love  china";把首地址给string ;这个是对字符指针变量赋值


也等价于 char  str[14]="i love  china"


 


 


 


 


函数声明:U8 D12RdEp(U8 Ep,U8 buf[],U8 cnt)和


                   U8 D12RdEp(U8 Ep,U8 *buf,U8 cnt是一样的


 


 


1.strncmp的用法


用法:#include <string.h>
 
  功能:比较字符串s1和s2的前n个字符。
 
  说明:
        当s1<s2时,返回值<0
        当s1=s2时,返回值=0
        当s1>s2时,返回值>0
 
  举例:

      // strncmp.c
     
      #include <syslib.h>
      #include <string.h>

      main()
      {
        char *s1="Hello, Programmers!";
        char *s2="Hello, programmers!";
        int r;
       
        clrscr();
       
        r="strncmp"(s1,s2,6);
        if(!r)
          printf("s1 and s2 are identical");
        else
        if(r<0)
          printf("s1 less than s2");
        else
          printf("s1 greater than s2");
       
        getchar();
        clrscr();
       
        r="strncmp"(s1,s2,10);
        if(!r)
          printf("s1 and s2 are identical");
        else
        if(r<0)
          printf("s1 less than s2");
        else
          printf("s1 greater than s2");

        getchar();
        return 0;
      }


 


2.unsigned short 表示0-65535  unsigned int 视情况而定,可能为2个字节,可能为4个字节


3. void *memset(void *s,  int c, size_t n); memset:作用是在一段内存块中填充某个给定的值,它对较大的结构体或数组进行清零操作的一种最快方法。


4.C/C++语言中的strlen与sizeof的区别


  1.从功能定义上,strlen函数,用来求字符串的长度,sizeof函数是用来求指定变量或变量类型等所占用内存的大小;


  2.sizeof是运算符,而strlen是C库函数strlen只能用char*做参数,且以'\0'结尾的;


  对于静态数组处理:

     char str[20]="0123456789";

     strlen(str)=10;   //表示数组中字符串的长度

     sizeof(str)=20;   //表示数组变量分配的长度

  对于指针处理:

     char *str="0123456789";

     strlen(str)=10;     //表示字符串的长度

     sizeof(str)=4;      //表示指针变量的所占内存大小

     sizeof(*str)=1;     //表示'0'这个字符变量的所占内存大小

 

5.关于memcpy的用法
结构如下:

void *memcpy(   void *dest,   const void *src,   size_t count );

作用:在dest处拷贝src处的字节,并以count来计算需要拷贝的字节数量,进行内存的拷贝。

参数:

dest:新的存贮区的开始部位   src:需要拷贝的开始部位    count:需要拷贝的字节数长度

备注:dest,src,它们都是从各自的地址处进行写入,如果是p而不是&p,那么将会取得p的值(地址),在该值的地址处进行读出或写入。

例:


  int* intPoint = new int(3333);

  int* intPoint1;

  memcpy( &intPoint1, &intPoint, 4 );//在intPoint1的地址处写入intPoint地址处的值,也就是intPoint指针值。

 

 

6.函数原型:extern char *strchr(char *str,char character)

参数说明:str为一个字符串的指针,character为一个待查找字符。
       
所在库名:#include <string.h>
 
函数功能:从字符串str中寻找字符character第一次出现的位置。
 
返回说明:返回指向第一次出现字符character位置的指针,如果没找到则返回NULL。


其它说明:还有一种格式char *strchr( const char *string, int c ),这里字符串是以int型给出的。


实例:



#include<string.h>
#include
<stdio.h>
int main()
...
{
    
char *str="Hello,I am sky2098,I liking programing!"
;
    
char character='k' ;  //指定一个字符

    char *strtemp;

    strtemp
=
strchr(str,character);
    
if(strtemp!=
NULL)
    
...
{
        printf(
"%s "
,strtemp);
    }

    
else
    
...{
        printf(
"can not find %c !"
,strtemp);
    }

    
return 0;
}

在VC++ 6.0编译运行:


点击看大图


注意返回字符串包含我们character字符。 


我们把下面定义:


char character='k' ;  //指定一个字符


改写成:


int character='k' ;  //指定一个字符


也同样能够实现。
7.原型:extern int memcmp(void *buf1, void *buf2, unsigned int count);
       
  用法:#include <string.h>
 
  功能:比较内存区域buf1和buf2的前count个字节。
 
  说明:
        当buf1<buf2时,返回值<0
        当buf1=buf2时,返回值=0
        当buf1>buf2时,返回值>0
 


1,这两个概念都是简称,指针函数是指带指针的函数,即本质是一个函数。我们知道函数都有返回类型(如果不返回值,则为无值型),只不过指针函数返回类型是某一类型的指针。其定义格式如下所示:


返回类型标识符 *返回名称(形式参数表)
{ 函数体 }


返回类型可以是任何基本类型和复合类型。返回指针的函数的用途十分广泛。事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于一个指针。比如函数返回一个整型值,实际上也相当于返回一个指针变量的值,不过这时的变量是函数本身而已,而整个函数相当于一个“变量”。例如下面一个返回指针函数的例子:


#include


float *find();
main()
{
    static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}};
    float *p;
    int i,m;
    printf("Enter the number to be found:");
    scanf("%d",&m);
    printf("the score of NO.%d are:\n",m);
    p="find"(score,m);
    for(i=0;i<4;i++)
        printf("%5.2f\t",*(p+i));
}


float *find(float(*pionter)[4],int n)/*定义指针函数*/
{
    float *pt;
    pt=*(pionter+n);
    return(pt);
}


学生学号从0号算起,函数find()被定义为指针函数,起形参pointer是指针指向包含4个元素的一维数组的指针变量。pointer+1指向score的第一行。*(pointer+1)指向第一行的第0个元素。pt是一个指针变量,它指向浮点型变量。main()函数中调用find()函数,将score数组的首地址传给pointer.


2,“函数指针”是指向函数的指针变量,因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上一致的。函数指针有两个用途:调用函数和做函数的参数。函数指针的说明方法为:
数据类型标志符 (*指针变量名)(参数);注:函数括号中的参数可有可无,视情况而定。
下面的程序说明了函数指针调用函数的方法:


#include


int max(int x,int y){ return(x>y?x:y); }


void main()
{
    int (*ptr)();
    int a,b,c;
    ptr="max";
    scanf("%d,%d",&a,&b);
    c=(*ptr)(a,b);
    printf("a=%d,b=%d,max=%d",a,b,c);
}


ptr是指向函数的指针变量,所以可把函数max()赋给ptr作为ptr的值,即把max()的入口地址赋给ptr,以后就可以用ptr来调用该函数,实际上ptr和max都指向同一个入口地址,不同就是ptr是一个指针变量,不像函数名称那样是死的,它可以指向任何函数,就看你像怎么做了。在程序中把哪个函数的地址赋给它,它就指向哪个函数。而后用指针变量调用它,因此可以先后指向不同的函数,不过注意,指向函数的指针变量没有++和--运算,用时要小心。 


 



//2~36进制 转 十进制
unsigned int OthToDec(char *oth, int base)
{
   unsigned int i=0, dec=0;
   while (oth)
   {
      dec*=base;
      if (oth>='0' && oth<='9')
         dec+=oth&15;
      else if (oth>='A' && oth<='Z')
         dec+=oth-55;
      else if (oth>='a' && oth<='z')
         dec+=oth-87;
      i++;
   }
   return dec;
}

//字符串形式十进制 转 十进制
//比如:"12" 转化为 12
unsigned int StrToDec(char *str)
{
   char *tmp=str;
   unsigned int dec=0;
   while (*tmp) dec=dec*10+(*tmp++&15);
   return dec;
}

/*
如果只有一个参数,则这个参数为要转换的数
如果有两个参数,第一个参数往往都存放其他进制数,第二个参数为要转换的数。
如果有三个参数,第一个参数往往都存放其他进制数,第二个参数为要转换的数,第三个为进制
比如:DecToOth(oth, 18, 8)即可把18转换为八进制的"22",由oth存放
*/



2~36

//二进制 转 十进制
//比如 "101" 转换为 5
unsigned int BinToDec(char *bin)
{
   char *tmp=bin;
   unsigned int dec=0; 
   while (*tmp) dec=(dec<<1)+(*tmp++&1);
   return dec;
}

//十进制 转 二进制
//比如 5 转换为 "101"
char *DecToBin(char *bin, unsigned int dec)
{
   char ch, *left=bin, *right=bin;
   do *right++=dec&1|'0';
   while (dec>>=1);
   *right--='\0';
   while (left<right)
   {
      ch=*left;
      *left++=*right;
      *right--=ch;
   }
   return bin;
}

//十进制 转 十六进制
//比如 18 转换为 "12"
char *DecToHex(char *hex, unsigned int dec)
{
   char ch, *left=hex, *right=hex, num[]="0123456789ABCDEF";
   do *right++=num[dec&15];
   while (dec>>=4);
   *right--='\0';
   while (left<right)
   {
      ch=*left;
      *left++=*right;
      *right--=ch;
   }
   return hex;
}

//十进制 转 2~36进制
char *DecToOth(char *oth, unsigned int dec, int base)
{
   char ch, *left=oth, *right=oth, num[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   do *right++=num[dec%base];
   while (dec/=base);
   *right--='\0';
   while (left<right)
   {
      ch=*left;
      *left++=*right;
      *right--=ch;
   }
   return oth;
}

//十进制 转 字符串形式十进制
//比如:123 转化为 "123"
char *DecToStr(char *str, unsigned int dec)
{
   char ch, *left=str, *right=str;
   do *right++=dec%10|'0';
   while (dec/=10);
   *right--='\0';
   while (left<right)
   {
      ch=*left;
      *left++=*right;
      *right--=ch;
   }
   return str;
}

//十六进制 转 十进制
//比如:"12" 转化为 18
unsigned int HexToDec(char *hex)
{
   unsigned int i=0, dec=0;
   while (hex)
   {
      dec<<=4;
      if (hex>='0' && hex<='9')
         dec+=hex&15;
      else if (hex>='A' && hex<='F')
         dec+=hex-55;
      else if (hex>='a' && hex<='f')
         dec+=hex-87;
      i++;
   }
   return dec;
}

//十六进制 转 字符串
//比如 "4142" 转换为 "AB"(0x41是'A',0x42是'B')
char *HexToStr(char *str, char *hex)
{
   char ch, *tstr=str, *thex=hex;
   while (*thex)
   {
      if ((ch=*thex++)<='9') *tstr=ch&15;
      else if (ch<='F') *tstr=ch-55;
      else *tstr=ch-87;
      *tstr<<=4;
      if ((ch=*thex++)<='9') *tstr+++=ch&15;
      else if (ch<='F') *tstr+++=ch-55;
      else *tstr+++=ch-87;
   }
   *tstr='\0';
   return str;
}

C指针   指向函数、数组和指针的指针



指向函数的指针


  我们知道,一个指针变量可以指向整型变量,字符串,数组,也可以指向一个函数。一个函数在编译的时候被分配给一个入口地址,这个入口地址就称为函数的指针。可以用一个指针变量指向函数,然后通过指针变量调用这个函数。因为每个函数都占有一段内存单元,它们有一个起始地址。所以,我们可以用一个指针变量指向一个函数,通过指针变量来访问它指向的函数。


如:


#include "stdio.h"


main()


{


    int max( int,int );


    int (* p)();


    int a,b,c;


    p = max;


    scanf( "%d,%d",&a,&b );


    c = (* p)(a,b);


    printf( "a = %d,b = %d,max = %d",a,b,c );


    getch();


}


<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 


max( int x,int y )


{


    int z;


    if( x>y )z = x;


    else z = y;


    return(z);


}


我们看到,其中int (* p)();首先,p*结合,表明了p是一个指针变量,后面的括号表明指针是指向函数的。 int表明了此函数带回了整型的返回值


赋值语句“p = max;”的作用是将函数max 的入口地址赋给指针变量p。和数组名代表数组起始地址一样,函数名代表该函数的入口地址。也就是说,pmax都指向函数的开头。值得注意的是,p是指向函数的指针变量,它只能指向函数的入口处,而不能指向函数中间的某一条指令处,因此不能用*p+1)来表示下一个指令。


这里说明一下,


(1)       指向函数的指针变量的一般形式为:


数据类型   * 指针变量名 )();


数据类型指的是函数返回值的类型。


(2)       函数的调用可以通过函数名调用,也可以通过函数指针调用。


(3)          *p)()表示定义一个指向函数的指针变量,它不固定指向哪一个函数,而只是表示定义了这样一个类型的变量,它是专门用来存入函数的入口地址的。要调用的时候,程序把哪一个函数的地址赋给它,它就指向哪一个函数。也就是说,一个指针变量可以先后指向返回类型相同的不同函数。


(4)          在给函数指针变量赋值时,只需要给出函数名而不必给出参数。如:


P = max;


因为是将函数入口地址赋给p,而不牵涉到实参与形参的结合问题。不能写成“p = max(a,b)”形式。


(5)          在函数指针变量调用时,只需要将(*p)代替函数名即可。在(*p)后的括号中根据需要写上实参。如下面程序表示:“调用由p指向的函数,实参为a,b。得到的函数值赋给c。”


c = (* p)(a,b);


(6)对于指向函数的指针变量像p++,p—等运算是无意义的。


 


                指针数组和指向指针的指针


一个数组,其元素均为指针类型数据,称为指针数组。也就是说,指针数组中的每一个元素都相当于一个指针变量。一维指针数组的定义形式为:


类型名    * 数组名[数组长度]


例如:  int * p[22]


P先与[4]结合,形成p[22]的形式,就显然是数组形式,它有四个元素,然后再与p前面的“*”结合,“*”表示此数组是指针类型的,每个数组元素(相当于一个指针变量)都可以指向一个整型变量。


int array[10]={0,1,2,3,4,5,6,7,8,9},value;
value=array[0];//也可写成:value=*array;
value=array[3];//也可写成:value=*(array+3);
value=array[4];//也可写成:value=*(array+4);
上例中,一般而言数组名array 代表数组本身,类型是int [10],但如果把array 看做指针的话,它指向数组的第0 个单元,类型是int *,所指向的类型是数组单元的类型即int。因此*array 等于0 就一点也不奇怪了。同理,array+3 是一个指向数组第3 个单元的指针,所以*(array+3)等于3。其它依此类推。


char *str[3]={
"Hello,this is a sample!",
"Hi,good morning.",
"Hello world"
};
char s[80];
strcpy(s,str[0]);//也可写成strcpy(s,*str);
strcpy(s,str[1]);//也可写成strcpy(s,*(str+1));
strcpy(s,str[2]);//也可写成strcpy(s,*(str+2));
上例中,str 是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。把指针数组名str 当作一个指针的话,它指向数组的第0 号单元,它的类型是char**,它指向的类型是char *。*str 也是一个指针,它的类型是char*,它所指向的类型是char,它指向的地址是字符串"Hello,this is a sample!"的第一个字符的地址,即'H'的地址。 str+1 也是一个指针,它指向数组的第1 号单元,它的类型是char**,它指向的类型是char *。*(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向"Hi,good morning."的第一个字符'H',等等。



  下面总结一下数组的数组名的问题。声明了一个数组TYPE array[n],则数组名称array 就有了两重含义:第一,它代表整个数组,它的类型是TYPE [n];第二,它是一个指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也就是数组单元的类型,该指针指向的内存区就是数组第0 号单元,该指针自己占有单独的内存,注意它和数组第0 号单元占据的内存区是不同的。该指针的值是不能修改的,即类似array++的表达式是错误的。在不同的表达式中数组名array 可以扮演不同的角色。
在表达式sizeof(array)中,数组名array 代表数组本身,故这时sizeof 函数测出的是整个数组的大小。在表达式*array 中,array 扮演的是指针,因此这个表达式的结果就是数组第0 号单元的值。sizeof(*array)测出的是数组单元的大小。表达式array+n(其中n=0,1,2,....。)中,array 扮演的是指针,故array+n 的结果是一个指针,它的类型是TYPE*,它指向的类型是TYPE,它指向数组第n 号单元。故sizeof(array+n)测出的是指针类型的大小。


int array[10];
int (*ptr)[10];
ptr=&array;
上例中ptr 是一个指针,它的类型是int (*)[10],他指向的类型是int [10],我们用整个数组的首地址来初始化它。在语句ptr=&array 中,array 代表数组本身。
本节中提到了函数sizeof(),那么我来问一问,sizeof(指针名称)测出的究竟是指针自身类型的大小呢还是指针所指向的类型的大小?答案是前者。例如:
int (*ptr)[10];
则在32 位程序中,有:
sizeof(int(*)[10])==4
sizeof(int [10])==40
sizeof(ptr)==4
实际上,sizeof(对象)测出的都是对象自身的类型的大小,而不是别的什么类型的大小。


 


 


在函数中,如果碰到return 语句,那么程序就会返回调用该函数的下一条语句执行,也就是说跳出函数的执行,回到原来的地方继续执行下去。但是如果是在主函数中碰到return语句,那么整个程序就会停止,退出程序的执行。


--------------------------------------------------------------------------------------------------------------------------------------------------------------------


return是C++预定义的语句,它提供了种植函数执行的一种放大。当return语句提供了一个值时,这个值就成为函数的返回值.

  说到return,有必要提及主函数的定义,下面是从网络上找到的资料,好好消化吧,对了解主函数中返回值的理解有很大的帮助.

  很多人甚至市面上的一些书籍,都使用了void main( ) ,其实这是错误的。C/C++ 中从来没有定义过void main( ) 。C++ 之父 Bjarne Stroustrup 在他的主页上的 FAQ 中明确地写着 The definition void main( ) { /* ... */ } is not and never has been C++, nor has it even been C.( void main( ) 从来就不存在于 C++ 或者 C )。下面我分别说一下 C 和 C++ 标准中对 main 函数的定义。



1. C
  在 C89 中,main( ) 是可以接受的。Brian W. Kernighan 和 Dennis M. Ritchie 的经典巨著 The C programming Language 2e(《C 程序设计语言第二版》)用的就是 main( )。不过在最新的 C99 标准中,只有以下两种定义方式是正确的:
int main( void )
int main( int argc, char *argv[] )
(参考资料:ISO/IEC 9899:1999 (E) Programming languages — C 5.1.2.2.1 Program startup)
  当然,我们也可以做一点小小的改动。例如:char *argv[] 可以写成 char **argv;argv 和 argc 可以改成别的变量名(如 intval 和 charval),不过一定要符合变量的命名规则。

  如果不需要从命令行中获取参数,请用int main(void) ;否则请用int main( int argc, char *argv[] ) 。
main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的激活者(如操作系统)。

  如果 main 函数的最后没有写 return 语句的话,C99 规定编译器要自动在生成的目标文件中(如 exe 文件)加入return 0; ,表示程序正常退出。不过,我还是建议你最好在main函数的最后加上return 语句,虽然没有这个必要,但这是一个好的习惯。注意,vc6不会在目标文件中加入return 0; ,大概是因为 vc6 是 98 年的产品,所以才不支持这个特性。现在明白我为什么建议你最好加上 return 语句了吧!不过,gcc3.2(Linux 下的 C 编译器)会在生成的目标文件中加入 return 0; 。



3. 关于 void main
  在 C 和 C++ 中,不接收任何参数也不返回任何信息的函数原型为“void foo(void);”。可能正是因为这个,所以很多人都误认为如果不需要程序返回值时可以把main函数定义成void main(void) 。然而这是错误的!main 函数的返回值应该定义为 int 类型,C 和 C++ 标准中都是这样规定的。虽然在一些编译器中,void main 可以通过编译(如 vc6),但并非所有编译器都支持 void main ,因为标准中从来没有定义过 void main 。g++3.2 中如果 main 函数的返回值不是 int 类型,就根本通不过编译。而 gcc3.2 则会发出警告。所以,如果你想你的程序拥有很好的可移植性,请一定要用 int main 。


4. 返回值的作用
main 函数的返回值用于说明程序的退出状态。如果返回 0,则代表程序正常退出,否则代表程序异常退出。下面我们在 winxp 环境下做一个小实验。首先编译下面的程序:
int main( void )
{
return 0;
}
  然后打开附件里的“命令提示符”,在命令行里运行刚才编译好的可执行文件,然后输入“echo %ERRORLEVEL%”,回车,就可以看到程序的返回值为 0 。假设刚才编译好的文件是 a.exe ,如果输入“a && dir”,则会列出当前目录下的文件夹和文件。但是如果改成“return -1”,或者别的非 0 值,重新编译后输入“a && dir”,则 dir 不会执行。因为 && 的含义是:如果 && 前面的程序正常退出,则继续执行 && 后面的程序,否则不执行。也就是说,利用程序的返回值,我们可以控制要不要执行下一个程序。这就是 int main 的好处。如果你有兴趣,也可以把 main 函数的返回值类型改成非 int 类型(如 float),重新编译后执行“a && dir”,看看会出现什么情况,想想为什么会出现那样的情况。顺便提一下,如果输入 a || dir 的话,则表示如果 a 异常退出,则执行 dir 。



5. 那么 int main(intargc,char*argv[],char*envp[])呢?
  这当然也不是标准 C 里面定义的东西!char*envp[] 是某些编译器提供的扩展功能,用于获取系统的环境变量。因为不是标准,所以并非所有编译器都支持,故而移植性差,不推荐使用。
到了这里,你应该了解为什么主函数定义为 int返回类型,而且函数体里面有return 0;这个语句了吧.
下面具体说说我对return的应用的理解。

  只要一个函数的返回值是数字型的,那么就可以返回0(即return 0),其实你返回多少都没问题。一般情况下,C++做出来的函数都要求返回一个值,当函数执行正常,且达到了一般情况下的目的,那么就返回0表示正确的调用了该函数,这个0就是返回给主调函数以通知没有出错的;如果函数调用中出错,或者没有按照一般情况执行,那么就返回1,以告知主调函数采取响应策略;如果你在某个函数所在类的定义所在的头文件中定义了一组状态值(一般都是负整数),那么函数就可以返回不同的值以告之主调函数具体发生了什么异常或错误,这种情况一般用于函数功能独立性较差的的情况。所以一般不鼓励把函数返回类型定义为void,至少返回应该是int,而在函数的最后加上return 0.语句:
int func(参数列表)
{
……
……
……
Return 0;
}
  
在函数中,如果碰到return 语句,那么程序就会返回调用该函数的下一条语句执行,也就是说跳出函数的执行,回到原来的地方继续执行下去。但是如果是在主函数中碰到return语句,那么整个程序就会停止,退出程序的执行。
  如果你定义一个函数有返回类型,可以想下面那样调用:
int func()
{
int value;
……
……
……
return value;
}
int main()
{
int intvalue;
intvalue=func();
……
……
teturn 0;
}



return语句后面具体是什么内容,这就要具体情况具体分析了:
(1) 在返回类型是char的函数中,return后应该是char类型的值;
(2) 在返回类型是int的函数中,如果是要停止函数的调用,最好应该为0;其他的按照你的目的而定,只要是int 类型就行了
(3) 在返回类型是结构类型的函数中,return后应该是结构的一个实例对象。
总之,函数定义为什么样的返回类型,该函数中return后就应该是相应类型的值。



 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
5
关闭 站长推荐上一条 /3 下一条