C语言 指针

# 指针和数组   

  计算机的硬件指令很大程度上要依赖于地址,所以指针是你能够类似于计算机底层的表达方式来表达自己的意愿;这使得使用指针的程序有着更高的运行效率。特别地,指针能够更有效地处理数组,数组标记实际上是一种变相使用指针的方式。   

  数组名同时也是该数组首元素的地址。

  ```

  flizny = &flizny[0]        //数组名是该数组元素的首地址

  ```

  flizny和&flizny[0]都代表首元素的内存地址(&是地址运算符),两者都是常量,因为在程序运行的过程中它们保持不变。然而可以把他们作为赋给指针变量的值,然后你可以修改指针变量的值,如下面程序所示


```

//pnt_add.c        //指针加法

#include 

#define SIZE    4

int main(void)

{

    short dates [SIZE];

    short * pti;

    short index;

    double bills[SIZE];

    double * ptf;

    pti = dates;        //把数组地址赋给指针;

    ptf = bills;    

    printf("%23s %10s\n", "short", "double");

    for(index = 0; index < SIZE; index++)

    {

        printf("pointers + %d: %10p %10p\n", index, pti+index, ptf+index);

    }

    return 0;

}

```

运行后,我的计算机上输出以下结果

```

                      short    double

pointers + 0:  0061FF0C  0061FEE8

pointers + 1:  0061FF0E  0061FEF0

pointers + 2:  0061FF10  0061FEF8

pointers + 3:  0061FF12  0061FF00

```

可以看出,在short为2个字节,double为8个字节。在C中,对一个指针加1的结果是对该指针增加一个存储单元。对数组而言,地址会增加到下一个元素的地址,而不是下一个字节。所以在声明指针是必须声明它所指向的类型,不然计算机无法得知存储对象所用的字节数。

---------------------------------------------------------------------------------

* 指针的数值就是他所指向的对象的地址。

* 在指针前使用运算符*就可以得到该指针所指向的对象的数值。

*对指针加1,等价于对指针的值加上它所指向的对象的字节大小。

```

dates + 2 == &dates[2]              //相同的地址

*(dates + 2) == dates[2]              //相同的值

*dates + 2                                    //第一个元素的值和2相加;间接运算符*优先级高于+,因此等价于(*dates)+2

```

这些关系总结了数组和指针间的密切关系:可以用指针标识数组的每个元素,并得到每个元素的数值。从本质上说,对同一个对象有两种不同的符号表示方法。C语言标准在描述数组是,也借助了指针的概念,例如,定义ar[n]时,意识是*(ar+n),即寻址到ar,然后移动n个单位,再取出数值。

----------------------------------------------------------------------------------

```

#include 

#define MONTHS 12

int main(void)

{

    int days[MONTHS] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    int index;

    for(index = 0; index < MONTHS; index++)

    {

        printf("Month %2d has %d days.\n", index + 1, *(days + index));

                                            //*(days + index)与days[index]相同

    }

    return 0;

}

```

运行程序的结果:

```

Month  1 has 31 days.

Month  2 has 28 days.

Month  3 has 31 days.

Month  4 has 30 days.

Month  5 has 31 days.

Month  6 has 30 days.

Month  7 has 31 days.

Month  8 has 31 days.

Month  9 has 30 days.

Month 10 has 31 days.

Month 11 has 30 days.

Month 12 has 31 days.

```

上面的程序展示了*(days + index)与days[index]等价,days是数组首元素的地址,days+index是元素days[index]的地址,*(days + index)是这个元素的值,与days[index]等价。

-------------

-------------

-------------

# 函数、数组和指针

假定一个返回数组中所有元素的和的函数:

```

int sun(int *ar, int n)

{

    int i;

    int toatl = 0;


    for( i = 0; i < n; i++)

    {

        total += ar[i];

    }


    return total;

}

```

第一个参数把数组地址和数组类型的信息传递给函数,第二个参数把数组中的元素个数传递给函数。

在函数原型或函数定义头的场合中(并且也只有这两种场合中),可以用 int *ar代替 int ar[]:

    int sum(int ar[], int n);

无论在任何情况下,形式int *ar都表示ar是指向int的指针。形式int ar[]也可以表示ar是指向int的指针,但只在声明形式参量时才可以这样使用。*PS: 在gcc version 8.2.0 (MinGW.org GCC-8.2.0-3)下使用int ar[]作为函数的形参已经会报错,修改为int*  **ar就没问题*



#    指针操作

* 赋值:可以把一个地址赋给指针。通常使用数组名或地址运算符&来进行地址赋值。

* 求值或取值:运算符*可以取出指针地址中所存储的数值。

* 取指针地址:使用运算符&可以得到存储指针本身的地址。

* 将一个整数加给指针:可以使用+运算符来把一个整数加给指针,或者把一个指针加给一个整数。两种情况下,这个整数都会和指针所指的    类型的字节数相乘,然后得到的结果会加到初始地址上。

* 增加指针的值:可以通过一般的加法或增量运算来增加一个指针的值,对指向某数组元素的指针做增量运算,可以让该指针指向下一个地址。

* 从指针中减去一个整数:可以使用-运算符来从一个指针中减去一个整数。指针必须是第一个操作数,或者是一个指向整数的指针。这个整数都会和指针所指向的类型的字节数相乘,然后所得的结果会从初始地址中减掉。

*减小指针的值:指针也可以做减量运算。

*求差值:可以求出两个指针之间的差值。通常对分别指向同一个数组的两个内存元素的指针求差值,以求出元素之间的距离。

*比较:可以使用比较运算符来比较两个指针的值,前提是两个指针具有相同的类型。

使用指针,有一个规则需要特别注意:不能对未初始化的指针取值,例如下面的例子:

```

int *pt;

*pt = 5;

```

程序的第二行表示把数值5存储到pt所指向的位置,但由于pt没有被初始化,因此他的值是随机的,不知道5将会被存储到什么位置。因此,在使用指针之前,必须要给他赋予一个已分配的内存地址。

你可能感兴趣的:(C语言 指针)