数组指针

数组指针

一个变量有一个地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址,且连续分布。所谓数组的指针是指数组的起始地址,数组元素的指针是数组元素的地址。

字节是内存中的最小可操作单元,通常将一个字节称为一个内存单元。

一个数组是由连续的一块内存单元组成的。数组名就是这块连续内存单元的首地址。一个数组也是由各个数组元素(下标变量)组成的。每个数组元素按其类型不同占有几个连续的内存单元。一个数组元素的首地址也是指它所占有的几个内存单元的首地址。

通过指针引用数组

引入指针变量后,就可以用两种方法访问数组元素。 p的初值为&a[0],则:

  • p+i 和 a+i 就是 a[i] 的地址,或者说它们指向a数组的第 i 个元素。
  • *(p+i)*(a+i) 就是 p+i 或 a+i 所指向的数组元素(的内容),即a[i]。例如,*(p+5)*(a+5) 就是 a[5]。
  • 指向数组的指针变量也可以带下标,如 p[i] 与 *(p+i) 等价。

根据以上叙述,引用一个数组元素可以用:

  • 下标法:即用 a[i] 形式访问数组元素,在前面介绍数组时都是采用这种方法。
  • 指针法:即采用 (a+i) 或 (p+i) 形式,用间接访问的方法来访问数组元素,其中a是数组名,p是指向数组的指针变量,它们的值相同。
C语言用数组作函数参数
  • 按值传递:用普通变量做函数参数,形参和实参位于不同的内存区域,发生函数调用时,会把实参的值传递给形参,改变形参的值不会影响到实参,它们是相互独立的。
  • 按引用传递: 在用数组名作函数参数时,不是进行值的传送,不会把实参数组的每一个元素的值都赋予形参数组的各个元素。因为实际上形参数组并不存在,编译系统不为形参数组分配内存。那么,数据的传送是如何实现的呢?数组名就是数组的首地址,用数组名作函数参数时所进行的传送只是地址的传送,也就是说把实参数组的首地址赋予形参数组名。形参数组名取得该首地址之后,也就等于有了实实在在的数组。实际上是形参数组和实参数组为同一数组,拥有同一段内存空间。这种传值方式成为按引用传递。 用普通变量作函数参数时,所进行的值传递是单向的,只能从实参传向形参,不能从形参传回实参。形参的初值和实参相同,而形参的值发生改变后,实参并不变化,两者的终值是不同的。而当用数组作函数参数时,情况有所不同。由于实际上形参和实参为同一数组,因此当形参数组发生变化时,实参数组也随之变化。
C语言字符串指针

C语言中,通过字符数组存放一个字符串,也可以用字符指针指向一个字符串。

  • 对指向字符变量的指针变量应赋予该字符变量的地址。
    char c, *p=&c;
    
  • 表示p是一个指向字符变量c的指针变量
  • 下面表示s是一个指向字符串的指针变量。把字符串的首地址赋予s
    char *string = "I love coding";
    
指针型函数

前面我们介绍过,所谓函数类型是指函数返回值的类型。函数的返回值是一个指针(即地址),这种返回指针值的函数称为指针型函数。定义指针型函数的一般形式为:

数据类型 *函数名(形参列表) {
  // 函数体
}
代码示例#2.6.1-比较两个字符串的长度
#include <stdio.h>
char *func(char *str1, char *str2){
    if(strlen(str1) >= strlen(str2)){
        return str1;
    }else{
        return str2;
    }
}

int main()
{
    char *s1 = "C Language";
    char *s2 = "C is very great!";
    char *longstr = func(s1, s2);
    printf("Long string: %s\n", longstr);

    return 0;
}
指针数组

指针数组中每个元素的值都为指针。一般的定义形式为:

数据类型 *数组名[数组长度];

用pa表示二维数组,pa是一个指针数组,有三个元素,每个元素值都是一个指针,指向整型变量。

int *pa[3]{ a[0], a[1], a[2]};
指针的指针

如果一个指针变量存放的又是另一个指针变量的地址,则称这个变量为指向指针的指针变量或指向指针的指针。

数据类型 **变量名;