设为首页 加入收藏

TOP

《C和指针》看书笔记(三)
2014-11-23 23:36:32 来源: 作者: 【 】 浏览:33
Tags:指针 看书 笔记
*vp = 0;

由标准可以,第二个for语句是有问题的.但实际上,在绝大多数C编译器中,这个循环将顺利完成任务.然而,你还是应该避免使用它,因为标准并不保语它可行.你迟早可能遇到一台这个循环失败的机器.对于负责可移植代码的程序员而言,这类问题简直就是个恶梦.

数组:

int a;

int b[10];

b[4]的类型是整型,但b的类型又是什么呢 它所表示的又是什么呢 一个合乎逻辑的答案是它表示整个数组,但事实并非如此.在C中,在几乎所有使用数组名的表达式中,数组名的值是一个指针常量,也就是数组第1个元素的地址.它的类型取决于数组元素的类型:如果它们是int类型,那么数组名的类型就是”指向int的常量指针”;如果它们是其它类型,那么数组名就是”指向其它类型的常量指针”.

只有在两种场合下,数组名并不用指针常量来表示------就是当数组名作为sizeof操作符或单目操作符的操作数时.sizeof返回整个数组的长度,而不是指向数组的指针的长度,取一个数组名的地址所产生的是一个指向数组的指针!

数组和指针

指针和数组并不是相等的,为了说明这个概念,请考虑下面这两个声明:

int a[5];

int b;

a和b能够互换使用吗 它们都具有指针值,它们都可以进行间接访问和下标引用操作.但是它们还是存在相当大的区别.

声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值是一个常量,指向这段空间的起始位置.声明一个指针变量时,编译器只为指针本身保留内存空间,它并不为任何整型值分配内存空间.而且,指针变量并未被初始化为指向任何现有的内存空间,如果它是一个自动变量,它甚至根本不会被初始化.因此,上述声明之后,表达式*a是完全合法的,但表达式*b却是非法的.*b将访问内存中某个不确定的位置,或者导致程序终止.另一方面,表达式b++可以通过编译,但a++却不行,因为a的值是一个常量.

字符数组的初始化

char message[] = { ‘H’, ‘e’, ‘l’, ‘l’, ‘o’, 0};

这个方法当然可行.但除了非常短的字符串,这种方法确实很笨拙.因此,语言标准提供了一种快递方法用于初始化字符数组:

char message[] = “Hello”;

尽管它看上去像是一个字符串常量,实际上并不是.它只是前例的初始化例表的另一种写法.

如果它们看上去完全相同,你如何分辨字符串常量和这种初始化例快递记法呢 它们是根据它们所处的上下文环境进行区分的.当用于初始化一个字符数组时,它已经一个初始化例表.在其他任何地方,它都表示一个字符串常量.

这里有一个例子:

char message[] = “Hello”;

char *message = “Hello”;

这两个初始化看上去很像,但它们具有不同的含义.前者初始化一个字符数组的元素,而后者则是一个真正的字符串常量.这个指针变量被初始化为指向这个字符串常量的存储位置.

多维数组:

考虑下列这些维数不断增加的声明:

int a;

int b[10];

int c[6][10];

int d[3][6][10];

a是个简单的整数.接下来的那个声明增加了一个维数,所以b就是一个向量,它包含10个整型元素.

c只是在b的基础上再增加了一维,所以我们可以把c看作是一个包含6个元素的向量,只不过它的每个元素本身是一个包含10个整型元素的向量.换句话说,c是一个一维数组的一维数组.d也是一如此:它是包含3个元素的数组.简洁的说,d是一个3排6行10列的整型三维数组.

数组名

一维数组名的值是一个指针常量,它的类型是”指向元素类型的指针”,它指向数组的第1个元素.多维数组也差不多简单.唯一的区别是多维数组第1维元素实际上是另一个数组.例如,下面这个声明:

int matrix[3][10];

matrix这个名字的值是一个指向它第1个元素的指针,所以matrix是一个指向一个包含10个整型元素的数组的指针.

指向数组的指针:

下面这些声明合法吗

int vector[10], *vp = vector;

int matrix[3][10], *mp = matrix;

第一个声明是合法的.它为一个整型数组分配内存,并把vp声明为一个指向整型的指针,并把它初始化为指向vector数组的第1个元素.vector和vp具有相同的类型:指向整型的指针.但是第二个声明是非法的.它正确地创建了matrix数组,并把mp声明为一个指向整型的指针.但是mp的初始化是不正确的,因为matrix并不是一个指向整型的指针,而是一个指向整型数组的指针.我们应该怎样声明一个指向整型数组的指针的呢

int (*p)[10];

这个声明比我们以前见过的所有声明更为复杂,但它事实上并不是很难.你只要假定它是一个表达式并对它进行求值.下标引用的优先级高于间接访问,但由于括号的存在,首先执行的还是间接访问,所以,p是一个指针,但它指向什么呢 接下来扫行的是下标的引用,所以p指向某种类型的数组.这个声明表达式中并没有更多的操作符,所以数组的每个元素都是整数.

声明并没有直接告诉你p是什么,但推断它的类型并不困难-----当我们对它执行间接访问操作时,我们得到的是个数组,对该数组进行下标引用操作得到的是一个整型值.所以p是一个指向整型数组的指针.

在声明中加上初始化后是下面这个样子:

int (*p)[10] = matrix;

它使p指向matrix的和1行.

p是一个指向拥有10个整型元素的数组的指针.当你把p与一个整数相加时,该整数值首先根据10个整型值的长度进行调整,然后再执行加法.所以我们可以使用这个指针一行一行地在matrix中移动.

如果你需要一个指针逐个访问整型元素而不是逐行在数组中移动,你应该怎么办呢 下面两个声明都创建了一个简单的整型指针,并以两种不同的方式进行初始化,指向matrix的第1个整型元素.

int *pi = &matrix[0][0];

int *pi = matrix[0];

增加这个指针的值使它指向下一个整型元素.

指针数组

int *api[10];

为了弄清楚这个复杂的声明,我们假定它是一个表达式,并对它进行求值.

下标引用的优先级高于间接访问,所以在这个表达式中,首先执行下标引用.因此,api是某种类型的数组(噢! 顺便说一下,它包含的元素个数为10).在取得一个数组元素之后,随即执行的是间接访问操作.这个表达式不再有其它操作符,所以它的结果是一个整型值.对数组的某个元素执行间接访问操作后,我们得到一个整型值,所以api肯定是个数组,它的元素类型是指向整型的指针.

高级指针话题

int *f();

要想推断出它的含义,你必须确定表达式*f()是如何进行求值的.首先执行的是函数调用操作符(),因为它的优先级高于间接访问操作符.因此,f是一个函数,它的返

首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇一步一步写算法(之基数排序) 下一篇一步一步写算法(之数据选择)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: