笔记------指针与数组

    以下的知识点总结于《c陷阱与缺陷》

    1.指针与数组

    c语言中的数组值得注意的地方有以下两点:

    (1).c语言中只有一维数组,而且数组的大小必须在编译期就作为一个常数确定下来。

    (2).对于一个数组,我们只能够做两件事:确定该数组的大小,以及获得指向该数组下标为0的元素的指针。其它有关数组的操作,哪怕它们咋看上去是以数组下标进行运算的,实际上都是通过指针进行的。换句话说,任何一个数组下标运算都等同于一个对应的指针运算。

   现在考虑下面的例子:

       int calendar[12][31];
     这个语句声明了calendar是一个数组,该数组拥有12个数组类型的元素,其中每个元素都是一个拥有31个整型元素的数组(而不是一个拥有31个数组类型的元素的数组,其中每个元素又是一个拥有12个整型元素的数组)。

    下面我们再看

    

    int *p;
    p = calendar;

     这个语句是非法的。因为calendar是一个二维数组,即“数组的数组“,在此处的上下文中使用calendar名称会将其转换为一个指向数组的指针;而p是一个整型变量的指针,这个语句试图将一种类型的指针赋值给另一种类型的指针,所以是非法的。

    很显然,我们需要一种声明指向数组的指针的方法。

    

  int  (*ap)[31];

    这个语句的实际效果是,声明了*ap是一个拥有31个整型元素的数组,因此ap就是一个指向这样的数组的指针。因而,我们可以这样写:

    int calendar[12][31];
    int (*monthp)[31];
    monthp = calendar;


    这样,monthp将指向数组calendar的第一个元素,也就是数组calendar的12个有着31个元素的数组类型元素之一。


    2.非数组的指针

    假定我们有两个这样的字符串s和t,我们希望将这两个字符串连接成单个字符串r。要做到这一点,我们可以借助常用的函数库strcpy和strcat。下面的方法似乎一目了然,可是却不能满足我们的目标:

    char *r;
    strcpy(r,s);
    strcat(r,t);


    之所以不行的原因在于不能确定r指向何处。我们还应该看到,不仅要让r指向一个地址,而且r所指向的地址处还应该有内存空间可供容纳字符串,这个内存空间应该是以某种方式已经被分配了的。

    我们再试一次,记住给r分配一定的内存空间:

    char r[100];
    strcpy(r,s);
    strcat(r,t);

只要s和t指向的字符串并不是太大,那么现在我们所用的方法就能够正常工作。不幸的是,c语言强制要求我们必须声明数组大小为一个常量,因此我们不能够确保r足够大。然而,大多数c语言实现为我们提供了一个库函数malloc,该函数接受一个整数,分配能够容纳同样数目的字符的一块内存。大多数C语言实现还提供了一个库函数strlen,该函数返回一个字符串中所包括的字符数。


    有了这两个库函数,似乎我们就能够像下面这样操作了:

    

char *r,*malloc();
r = malloc(strlen(s) + strlen(t));
strcpy(r,s);
strcat(r,t);
    这个例子还是错的,原因有三。

 第一个原因,malloc函数有可能无法提供请求的内存。

    第二个原因,给r分配的内存在使用完之后应该及时释放,这一点务必要记住。

    第三个原因,也是最重要的原因,就是前面的例程在调用malloc函数时并未分配足够的内存。我们必须为r多分配一个字符的空间。

    做到了这些,并且注意检查了函数malloc是否调用成功,我们就得到正确的结果:

    

char *r,*malloc();
r = malloc(strlen(s)+strlen(t)+1);
if(!r){
    complain();//错误处理
    exit(1);
}

strcpy(r,s);
strcat(r,t);


/*一段时间之后在使用*/
free(r);

    3. 作为参数的数组声明

    在c语言中,我们没有办法可以将一个数组作为函数参数直接传递。

    如果我们使用数组名作为参数,那么数组会立刻被转化为指向该数组第1个元素的指针。

    c语言中会自动地将作为参数的数组声明转化为相应的指针声明。

    也就是说,像这样的写法:

    

int strlen( char s[])
{
  /* 具体内容*/
}

与下面的写法完全相同:

int strlen(char *s)
{
   /*具体内容*/
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值