首页 考试吧论坛 Exam8视线 考试商城 网络课程 模拟考试 考友录 实用文档 求职招聘 论文下载
2011中考 | 2011高考 | 2012考研 | 考研培训 | 在职研 | 自学考试 | 成人高考 | 法律硕士 | MBA考试
MPA考试 | 中科院
四六级 | 职称英语 | 商务英语 | 公共英语 | 托福 | 雅思 | 专四专八 | 口译笔译 | 博思 | GRE GMAT
新概念英语 | 成人英语三级 | 申硕英语 | 攻硕英语 | 职称日语 | 日语学习 | 法语 | 德语 | 韩语
计算机等级考试 | 软件水平考试 | 职称计算机 | 微软认证 | 思科认证 | Oracle认证 | Linux认证
华为认证 | Java认证
公务员 | 报关员 | 银行从业资格 | 证券从业资格 | 期货从业资格 | 司法考试 | 法律顾问 | 导游资格
报检员 | 教师资格 | 社会工作者 | 外销员 | 国际商务师 | 跟单员 | 单证员 | 物流师 | 价格鉴证师
人力资源 | 管理咨询师考试 | 秘书资格 | 心理咨询师考试 | 出版专业资格 | 广告师职业水平
驾驶员 | 网络编辑
卫生资格 | 执业医师 | 执业药师 | 执业护士
会计从业资格考试会计证) | 经济师 | 会计职称 | 注册会计师 | 审计师 | 注册税务师
注册资产评估师 | 高级会计师 | ACCA | 统计师 | 精算师 | 理财规划师 | 国际内审师
一级建造师 | 二级建造师 | 造价工程师 | 造价员 | 咨询工程师 | 监理工程师 | 安全工程师
质量工程师 | 物业管理师 | 招标师 | 结构工程师 | 建筑师 | 房地产估价师 | 土地估价师 | 岩土师
设备监理师 | 房地产经纪人 | 投资项目管理师 | 土地登记代理人 | 环境影响评价师 | 环保工程师
城市规划师 | 公路监理师 | 公路造价师 | 安全评价师 | 电气工程师 | 注册测绘师 | 注册计量师
缤纷校园 | 实用文档 | 英语学习 | 作文大全 | 求职招聘 | 论文下载 | 访谈 | 游戏
您现在的位置: 考试吧(Exam8.com) > 计算机等级考试 > 计算机二级 > C语言 > 复习资料 > 正文

计算机等考试C语言之指针、数组和函数

     基本解释
  1、指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);数组的本质则是一系列的变量。
  2、数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。
  3、当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。

  问题:指针与数组
  听说char a[]与char *a是一致的,是不是这样呢?
  答案与分析:
  指针和数组存在着一些本质的区别。当然,在某种情况下,比如数组作为函数的参数进行传递时,由于该数组自动退化为同类型的指针,所以在函数内部,作为函数参数传递进来的指针与数组确实具有一定的一致性,但这只是一种比较特殊的情况而已,在本质上,两者是有区别的。请看以下的例子:
char a[] = "Hi, pig!";
char *p = "Hi, pig!";
上述两个变量的内存布局分别如下:
  数组a需要在内存中占用8个字节的空间,这段内存区通过名字a来标志。指针p则需要4个字节的空间来存放地址,这4个字节用名字p来标志。其中存放的地址几乎可以指向任何地方,也可以哪里都不指,即空指针。目前这个p指向某地连续的8个字节,即字符串“Hi, pig!”。
  另外,例如:对于a[2]和p[2],二者都返回字符‘i’,但是编译器产生的执行代码却不一样。对于a[2],执行代码是从a的位置开始,向后移 动2两个字节,然后取出其中的字符。对于p[2],执行代码是从p的位置取出一个地址,在其上加2,然后取出对应内存中的字符。

  问题:数组指针
  为什么在有些时候我们需要定义指向数组而不是指向数组元素的指针?如何定义?
  答案与分析:
  使用指针,目的是用来保存某个元素的地址,从而来利用指针独有的优点,那么在元素需要是数组的情况下,就理所当然要用到指向数组的指针,比如在高维需要动态生成情况下的多维数组。
  定义例子如下: int (*pElement)[2]。
  下面是一个例子:
int array[2][3] = {{1,2,3},{4,5,6}};
int (*pa)[3]; //定义一个指向数组的指针
pa = &array[0]; // '&'符号能够体现pa的含义,表示是指向数组的指针
printf ("%d", (*pa)[0]); //将打印array[0][0],即1
pa++; // 猜一猜,它指向谁?array[1]?对了!
printf ("%d", (*pa)[0]); // 将打印array[1][0],即4
上述这个例子充分说明了数组指针—一种指向整个数组的指针的定义和使用。
  需要说明的是,按照我们在第四篇讨论过的,指针的步进是参照其所指对象的大小的,因此,pa++将整个向后移 动一个数组的尺寸,而不是仅仅向后移 动一个数组元素的尺寸。

  问题:指针数组
  有如下定义:
struct UT_TEST_STRUCT *pTo[2][MAX_NUM];
  请分析这个定义的意义,并尝试说明这样的定义可能有哪些好处?
  答案与分析:
  前面我们谈了数组指针,现在又提到了指针数组,两者形式很相似,那么,如何区分两者的定义呢?分析如下:
  数组指针是:指向数组的指针,比如 int (*pA)[5]。
  指针数组是:指针构成的数组,比如int *pA[5]。
  至于上述指针数组的好处,大致有如下两个很普遍的原因:
  a)、各个指针内容可以按需要动态生成,避免了空间浪费。
  b)、各个指针呈数组形式排列,索引起来非常方便。
  在实际编程中,选择使用指针数组大多都是想要获得如上两个好处。
问题:指向指针的指针
  在做一个文本处理程序的时候,有这样一个问题:什么样的数据结构适合于按行存储文本?
  答案与分析:
  首先,我们来分析文本的特点,文本的主要特征是具有很强的动态性,一行文本的字符个数或多或少不确定,整个文本所拥有的文本行数也是不确定的。这样的特征决定了用固定的二维数组存放文本行必然限制多多,缺乏灵活性。这种场合,使用指向指针的指针有很大的优越性。
  现实中我们尝试用动态二维数组(本质就是指向指针的指针)来解决此问题:
  图示是一个指针数组。所谓动态性指横向(对应每行文本的字符个数)和纵向(对应整个文本的行数)两个方向都可以变化。
  就横向而言,因为指针的灵活性,它可以指向随意大小的字符数组,实现了横向动态性。
  就竖向而言,可以动态生成及扩展需要的指针数组的大小。

[NextPage]

  下面的代码演示了这种动态数组的用途:
// 用于从文件中读取以 '\0'结尾的字符串的函数
extern char *getline(FILE *pFile);
FILE *pFile;
char **ppText = NULL; // 二维动态数组指针
char *pCurrText = NULL; // 指向当前输入字符串的指针
ULONG ulCurrLines = 0;
ULONG ulAllocedLines = 0;

while (p = getline(pFile))
{
 if (ulCurrLines >= ulAllocedLines)
 {
  // * 当前竖向空间已经不够了,通过realloc对其进行扩展。
 ulAllocedLines += 50; // 每次扩展50行。
  ppText = realloc (ppText, ulAllocedLines * (char *));
  if (NULL == ppText)
  {
   return; // 内存分配失败,返回
  }
 }
 ppText[ulCurrLines++] = p; // 横向“扩展”,指向不定长字符串
}

     问题:指针数组与数组指针与指向指针的指针
  指针和数组分别有如下的特征:
  指针:动态分配,初始空间小
  数组:索引方便,初始空间大
  下面使用高维数组来说明指针数组、数组指针、指向指针的指针各自的适合场合。
   多维静态数组:各维均确定,适用于整体空间需求不大的场合,此结构可方便索引,例a[10][40]。
   数组指针:低维确定,高维需要动态生成的场合,例a[x][40]。
   指针数组:高维确定,低维需要动态生成的场合,例a[10][y]。
   指向指针的指针:高、低维均需要动态生成的场合,例a[x][y]。

  问题:数组名相关问题
  假设有一个整数数组a,a和&a的区别是什么?
  答案与分析:
  a == &a == &a[0],数组名a不占用存储空间。需要引用数组(非字符串)首地址的地方,我一般使用&a[0],使用a容易和指针混淆,使用&a容易和非指针变量混淆。
  区别在于二者的类型。对数组a的直接引用将产生一个指向数组第一个元素的指针,而&a的结果则产生一个指向全部数组的指针。例如:
int a[2] = {1, 2};
int *p = 0;
p = a; /* p指向a[0]所在的地方 */
x = *p; /* x = a[0] = 1*/
p = &a; /* 编译器会提示你错误,*/
/*显示整数指针与整数数组指针不一样 */

      问题:函数指针与指针函数
   请问:如下定义是什么意思:
int *pF1();
int (*pF2)();
  答案与分析:
  首先清楚它们的定义:
   指针函数,返回一个指针的函数。
   函数指针,指向一个函数的指针。
  可知:
   pF1是一个指针函数,它返回一个指向int型数据的指针。
   pF2是一个函数指针,它指向一个参数为空的函数,这个函数返回一个整数。

文章搜索
版权声明:如果计算机等级考试网所转载内容不慎侵犯了您的权益,请与我们联系800@exam8.com,我们将会及时处理。如转载本计算机等级考试网内容,请注明出处。