• C——数组与指针


    多维数组

     

    1.       对两维数组的理解

    对于Float rain[5][12],把它理解为有这样一个数组,它的可以表示为rain[5],而其中的每一个元素(总共有5个)是另外一个数组,这个数组有12float类型的数据。

    所以rain的首元素rain[0]是一个包含12float数值的数组,且rain[1],rain[2]等等也是如此。换言之,rain是包含5个元素(每一个元素又是包含12float数的数组)的数组。

     

    2.       对于两维数组的地址计算

    根据刚才的分析,可以得出以下结论。

    如果有数组int a[3][3], 32位机子上运行,且假设a的地址为2000,那么a[1]的地址就是20122000 + 4 * 3),而且a[1]的地址就是a[1][0]的地址,正如a的地址就是a[0][0]的地址(数组名其实就是该数组首元素的地址)。

    另外,a[2][1] == *(*(a + 2) + 1) , 理解两维数组的关键是a[1]是个int *型指针,因为a[1]是指向其首元素a[1][0]的指针,而a[1][0]int * 型。

     

    3.       如何将数组作为参数传递到函数

    处理数组的函数其实使用指针指针作为参数的。在C中,a[i]在后台就是被解析为*(a + i)

    (1)     一维数组

    方法一,如果有float a[3],那么对应的函数原型至少为 int sum(float * a, int n),其中float * a 是因为以后将会传入数组名,而数组名就是数组第一个元素的地址,所以要与之匹配,对于这个例子,数组的第一个元素是float型,所以如果传入参数的话就应该是float*. int n是为了传入这个数组的大小,防止函数内越界。

     

    方法二,如果有float a[3],那么对应的函数原型至少为 int sum(float * a, float * end)

    调用如下 sum(a , a + 3)。然后需要在sum中做的事情是判断,注意在做while的时候的判定条件是 while ( a < end),其中千万不能用等号,因为a的最后一个元素为a[2]

     

    (2)     两维数组

    利用指针数组(形似int (*p)[2],函数原型写成 int sum( int (*p)[2], int rows)。其中要已知两维数组的列数为2,行数作为一个参数传进sum.

     

    4.       指针可以使用的基本操作

    (1)       赋值

    (2)       求值(*操作符)

    (3)       取指针的地址(&操作符)

    (4)       将整数加给指针(包括自加)

    (5)       从指针中减去一个整数(包括自减)

    (6)       求差值——通常对分别指向同一个数组内两个元素的指针求差值,以求出元素之间的距离。

    (7)       比较——前提是两个指针具有相同的类型

     

    5.       对指针的加减法运算

    C中,对一个指针加1的结果是对该指针增加1个存储单元(即它所指向的对象的字节大小)。比如说有int * p. 如果p的地址是2000,那么++p的结果是2004(在32位机子上,int占用4个字节)。

    对于数组而言,由于这个特性,地址会增加到下一个元素的地址。

       于是,如果有double dates[10],则显然 (date + 2) == &dates[2],而且*(dates + 2) == dates[2]

     

    注意,这里是对指针的加减法,虽然dates代表dates[0]的地址,但是它毕竟不是指针,而是地址的常量。所以语句dates++是违法的。

     

    6.       关于const int * pint  * const p

    前者constint *, p所指向的地址是不能够被改变了,但是这个地址所代表的内容却是可以改变的。后者constp,即p的内容(*p)是不能够被改变了,但是p所指向的地址却是可以转换的。

     

    7.       指针数组与数组指针

    关键在于[]的优先级高于*

    (1)     Int (*pz)[2]

    pz是一个指针,指向一个int[2]的匿名数组。

     

    (2)     Int * pz[2]

    Pz是一个数组,他有2个元素,而且每一个元素是int *型。

     

    8.       指针的兼容性

    指针赋值非常严格,只能够赋给相同类型的值。

    例如有如下声明:

    Int * pt;

    Int (*pa)[3];

    Int ar1[2][3];

    Int ar2[3][2];

    Int **p2

    那么有如下结论

    Pt = & ar1[0][0] //成立

    Pt = ar1[0] //成立 ,因为ar1[0]就是int * 型指针。可以这样理解。 &Ar1[0][0] == *(ar1 + 0) + 0

    Pt = ar1 // 非法,因为ar1是指向由3int值构成的数组的指针,说白了其实是一个int[3]型的指针,而不是int *型指针。Ar1是指向ar1[0]的指针,而ar1[0]是一个int[3],所以ar1int[3]型指针。

    Pa = ar1 // 成立,理由见上

    Pa = ar2 //不成立, 因为paint[3]型指针,而ar2int[2]型指针

    P2 = &pt //成立

    *p2 = ar2[0] //成立,因为ar2[0]int * 型指针,因为ar2[0]是指向其首元素ar2[0][0]的指针

    P2 = ar2 //不成立,p2int **,ar2int[2]型指针。

  • 相关阅读:
    werfault进程使用CPU率高
    oracel 拆分字符串
    TCP TIME WAIT
    netstat 命令
    Java 理论与实践: 并发集合类
    DIV与SPAN之间有什么区别
    oracle超出打开游标的最大数的原因和解决方案
    Quartz表达式
    Axis创建webservice客户端和服务端
    Web服务cxf框架发布2
  • 原文地址:https://www.cnblogs.com/aicro/p/1580084.html
Copyright © 2020-2023  润新知