C程序设计语言--指针与数组(一)

    关于这方面的文章,网上早就有人总结的非常完整了,但是还是想从自己的角度去分析下。

一、指针与地址

    指针是一种保存变量地址的变量。在ANSI C中使用类型void*(指向void的指针)代替char *作为通用指针的类型。一元运算符&可用于取一个对象的地址,因此,下列语句:p=&c;将把c的地址赋值给变量p,我们称p为“指向”c的指针。地址运算符&只能应用于内存中的对象,既变量与数组元素。它不能作用与表达式、常量或register类型的变量。(什么是不能作用与常量?)

    一元运算符*是间接寻址或间接引用运算符。当它作用域指针时,将访问指针所指向的对象。

    我们应该注意,指针只鞥指向某种特定类型的对象,也就是说,每个指针都必须指向某种特定的数据类型。(一个例外的情况是指向void类型的指针可以存放指向任何类型的指针,但它不能间接引用其自身。)

    一元运算符*和&的优先级比算术运算符的优先级高。因此,*p+=1是将ip指向的对象的值加1,它等同于++*p或(*p)++.语句(*p)++中的圆括号是必需的,否则,该表示将对p进行加1运算,而不是对p指向的对象进行加1运算。这是因为,类似于*和++这样的一元运算符遵循从右至左的结合顺序。在这里还对这篇文章里面的那些操作运算有疑问的地方可以解惑了吧!!

二、指针与函数参数

    由于C语言是以传值的方式将参数传递给被调用函数。因此,被调用函数不能直接修改主调函数中变量的值。由这句话引申出来的问题也不在少数,尤其是关于地址和值的诸多事情。要想达到目的可以使主调程序将指向所要交换的变量的指针传递给被调用函数,既swap(&a,&b);指针参数使得被调用函数能够访问和修改主调函数中对象的值。

三、指针与数组

    首先,通过数组下标所能完成的任何操作都可以通过指针来实现。但是数组申请的空间在内存中的存储是连续的区域。关于指针加1在索引数组的时候所带来的变化就不再累述了。无论数组中的元素的类型或数组长度是什么,“指针加1”就意味着,p+1指向p指向的对象的下一个对象。相应地,p+i指向p所指向的对象之后的第i个对象

    数组类型的变量或表达式的值是该数组第0个元素的地址。执行赋值语句p=&a[0]后,p和a具有相同的值。因为数组名所代表的就是该数组最开始的一个元素的地址,所以赋值语句p=&a[0]也可以写成p=a;

    在计算数组元素a[i]的值时,c语言实际上先将其转换为*(a+i)的形式,然后再进行求值。a+i是a之后的第i个元素的地址。

    但是,必须记住,数组名和指针之间有一个不同之处,指针是一个变量,因此,在C语言中,局域p=a和p++都是合法的。但数组名不是变量,因此,类似于a=p和a++形式的语句是非法的

    当把数组名传递给一个函数时,实际上传递的是该数组的第一个元素的地址。

四、地址算术运算

    如果p是一个指向数组中某个元素的指针,那么p++将对p进行自增运算并指向下一个元素,这类运算是指针或地址算术运算中最简单的形式。

    有效的指针运算包括相同类型指针之间的赋值运算:指针同整数之间的加法或减法运算;指向相同数组中元素的两个指针间的减法或比较运算;将指针赋值为0或指针与0之间的比较运算。其他所有形式的指针运算都是非法的。

五、字符指针与函数

    字符串常量是一个字符数组,例如:“i am a string”,在字符串的内部表示中,字符数组以空字符'\0'结尾,所以,程序可以通过检查空字符找到字符数组的结尾。字符串常量占据的存储单元数也因此比双引号内的字符数大1.

    下面两个定义:

    char amessage[]="fdsfs"; /* 定义一个数组*/

    char *pmessage="fdsafd"; /* 定义一个指针*/

上述声明中,第一个是一个仅仅足以存放初始化字符串以及空字符'\0'的一维数组。数组中的单个字符可以进行修改,但amessage始终指向同一个存储位置。pmessage是一个指针,其初始值指向一个字符串常量,之后它可以被修改以指向其他地址,但如果收修改字符串的内容,是不可以的

    说几个操作运算,*--p,在读取指针p指向的字符之前先对p执行自减运算。下面两个表达式:

    *p++=val; /* 将val压入栈*/

    val=*--p; /* 将栈顶元素弹出到val中 */ 是进栈多和出栈的标准用法。

六、指针数组以及指向指针的指针

    由于指针本事是变量,所以他们也可以像其他变量一样存储在数组中。所以指针数组,就是每一个元素都是指针:char *lineptr[10];由于[]操作符比*操作符优先级高。它表示lineptr是一个具有10个元素的一维数组,其中数组的每个元素是一个指向字符类型对象的指针。也就是说,lineptr[i]是一个字符指针,而*lineptr[i]是该指针指向的第i个文本行的首字符。

七、多维数组

    在C语言中,二维数组实际上是一种特殊的一维数组,它的每个元素也是一个一维数组。

    如果将二维数组作为参数传递给函数,那么在函数的参数声明中必须指明数组的列数。因此,如果将数组daytab作为参数传递给函数f,那么f的声明应该写成下列形式:

    f(int daytab[2][13]) {...}

    也可以写成

    f(int daytab[][13]) {.....}

    因为数组的行数无关紧要,所以,该声明还可以写成

    f(int (*daytab)[13]) {....}

这种声明形式声明参数是一个指针,它指向具有13个整形元素的一维数组。因为[]的优先级高于*的优先级,所以上述声明中必须使用圆括号。去掉括号,int *daytab[13] 这相当于声明了一个数组,该数组有13个元素,其中每个元素是一个指向整形对象的指针。

    在《C专家编程》这本书介绍了关于这个问题的解释,对于多维数组来说,传递给函数的参数必须是数组指针,不能是指针数组

八、指针与多维数组

    区分二维数组与指针数组之间的区别。

    int a[10][20];

    int *b[10];

从语法角度讲,a[3][4]和b[3][4]都是对一个Int对象的合法引用。但a是一个真正的二维数组,它分配了200个int类型长度的存储空间,并且通过常规的矩阵下标计算公式20*row+col(row为行,col为列)计算得到元素a[row][col]的位置。但是,对于b来说,该定义仅仅分配了10个指针,并且没有对他们初始化,他们的初始化必须以显示的方式进行,比如静态初始化或通过代码初始化。指针数组的一个好处:数组的每一行长度可以不同。(关注申请的问题)

九、指向函数的指针

    在C语言中,函数本身不是变量,但可以定义指向函数的指针。这种类型的指针可以被赋值、存放在数组中、传递给函数以及作为函数的返回值等等。

    int (*comp)(void*,void*)它表明comp是一个指向函数的指针,该函数具有两个void*类型的参数,其返回值类型为int.在下列语句

    if((*comp)(v[i],v[left])<0)comp的使用和其声明是一致的,comp是一个指向函数的指针,*comp代表一个函数。且不能去掉括号。

    总结:不再一味的看书中的内容,也不再一味的为了工整的博文而忘记了本质追求,总结了这一个月来的结构,学而不思则罔,思而不学则殆。前一条对自己非常的照应,倒不如弄懂一个模块,然后再去攻击另一个模块,各个攻破,还是这样安排合适。不管是内核还是语言,还有就是,记录的好东西不去整理仍然不是自己的,这个毛病也得改!!从善如流!!不要一味追求快,快没达到效果还不如慢的好。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值