C语言学习-指针与数组

1.指针与一维数组

 

1.1数组的地址

通过前面的学习,我们已经知道,数组是有一定顺序关系的若干变量的集合,占用连续的存储空间。集合中的每个变量也称作数组的元素。

C语言中,数组的地址是指数组在内存中的起始地址,即第一个数组元素的地址。一维数组的数组名代表一维数组的指针起始地址)。

       例如:int a[10];   &a[0]表示数组a的第一个元素地址,a为数组名是数组的首地址。两个表达式显然是相等的。

1.2数组元素的表示

1)下标法:通过变址运算符”[ ]”访问数组元素,如a[i]。

2)指针法:在数组中,指针的加法相当于指向数组的下一个元素,指针的减法相当于指向数组的上一个元素。

例如:若指针变量p指向数组a的首地址,则:a[i]、*(p+i)、 *(a+i) 和p[i]具有相同功能的功能:访问数组第i+1个数组元素。

C语言学习-指针与数组

 

事实上,C语言中指针的效率往往高于数组下标。因此a[i] <=> *(a+i) 在计算机内部实现的时候,数组下标都会转化为地址。

注意:上例中数组元素访问过程中,数组地址(数组名)与指针变量具有相同的访问效果。指针变量是变量。数组地址(数组名)是常量,不能自加或自减,不能改变。

C语言学习-指针与数组

 

1.3指针与数组常见操作总结

数组

指针表示

含义

array

&array[0]

 数组名是第一个元素的地址

*array

array[0]

 数组的第一个元素

array + i

&array[i]

 数组第i个元素的地址

*(array + i )

*(&array[i]) == array[i]

 数组第i个元素

*array + m

array[0] + m

 数组第一个元素加m

*array++

error

error

 

 

1.4  array&array之间的区别

       大家都应该知道,array和&array[0]代表的都是数组首元素的首地址,而如果你将&array的值打印出来,会发现该值也等于数组首元素的首地址,但是其含义是不同的。

       array+1或 &array[0]+1,表示数组下一个元素的地址。

       &array 代表整个数组的地址

所以 &array + 1 应该移动整个数组的大小(sizeof(a));

 

2.指针与二维数组

 

通过前面的学习,我们已经知道,多维数组就是具有两个或两个以上下标的数组。实际在C语言中,没有多维数组的概念,多维数组就是低维数组的的组合。例如二维数组,就可以看成由多个一维数组组成。

C语言学习-指针与数组

2.1列指针遍历二维数组元素

从内存管理的角度,二维数组的元素和一维数组的元素存储是类型的,都是连续存储,因此可以使用一级指针循环遍历二维数组中的所有元素。

C语言学习-指针与数组

C语言学习-指针与数组
从程序的运行结果,可以看到二维数组中,各元素的地址,如上图所示。由于一级指针p,p+i移动了i个元素,相当于移动了i列,因此也称指针p为列指针

 

2.2 行指针遍历二维数组元素

二维数组可以看成有多个一维数组组成的。比如int a[3][3],含有三个元素:a[0]、a[1]、a[2]

元素a[0]、a[1]、a[2]都是一维数组名,每个一维数组又包含三个元素。

C语言学习-指针与数组C语言学习-指针与数组

二维数组名代表数组的起始地址,数组名加1,是移动一行元素。因此,二维数组名常被称为行地址

 

2.3 表达二维数组中的元素

1)定义一个二维数组a,有3行3列,如何表达第二行第二个元素的地址?

int a[3][3] = { {1, 3, 5,}, {9, 11, 13}, {17, 19, 21} };

方法一:下标法

&a[1][1]

方法二:

a[1]表示一维数组名,就代表第二行第一列元素的地址,即&a[1][0]。所以a[1]+1表示a[1]数组的下一个元素地址即a[1][1]的地址等价于&a[1][0]+1。又由于a[1]等价于*(a+1),所以a[1][1]的地址也可以表示为*(a+1)+1

所以总结&a[1][0]+1 == a[1]+1 == *(a+1)+1

推导出a[i][j]的地址(&a[i][j])等于&a[i][0]+j => a[i]+j =>*(a+i)+j

2)如何表达第二行第二个元素的值?

       我们已经知道第二行第二个元素的地址了,在前面加个*,就能引用元素了

*(&a[i][j]) => *(&a[i][0]+j) => *(a[i]+j) => *(*(a+i)+j)

C语言学习-指针与数组

2.4行指针(数组指针)

对于二维数组来说,存储行地址的指针变量,叫做行指针变量。形式如下:

     <数据类型>   (*<指针变量名>)[表达式] ;

例如,int a[2][3];  int (*p)[3] = a;

当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。

C语言学习-指针与数组

在程序中,二维数组名和行指针在表达式形式上非常相似。本质区别是,数组名是地址常量,指针是变量

C语言学习-指针与数组

 

3.字符指针

 

我们把指向char数据类型的指针变量称为字符指针变量。在这里,重点介绍掌握字符指针处理字符串时的用法。

3.1字符指针与字符数组

在C语言中没有字符串数据类型。通常借助字符数组来存储字符串。

初始化字符指针是把内存中字符串的首地址赋予指针,即指针指向字符串第一个字符。这样可以用指针来处理字符串。(注意:并不是把该字符串复制到指针中。指针变量只有4个字节,只能用来保存地址)

eg:

    char  str[] = “Hello World”; 

    char  *p = str;

示例:编写一个程序实现功能,字符串翻转,用指针实现。

C语言学习-指针与数组

3.2 字符指针与字符串常量

在C编程中,当一个字符指针指向一个字符串常量时,不能修改指针指向的对象的值。

char  *p = “Hello World”; // 相当于const char *s = “Hello World”。字符串常量是存放在常量区的,不可修改。

*p = ‘h’;    // 错误, 不能修改常量