您的位置:首页 > 其它

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

2012-03-08 16:16 232 查看
以下的知识点总结于《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)
{
/*具体内容*/
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: