【C语言笔记】关于数组与指针的总结

参考:C语言中文网

前言

数组与指针有很密切的联系,常见的结合情况有以下三种:

  • 数组指针
  • 指针数组
  • 二维数组指针

数组指针

数组指针:指向数组的指针。如:

int arr[] = {0,1,2,3,4};

int *p = arr; 

//也可写作int *p=&arr[0]

也就是说,p,arr,&arr[0]都是指向数组的开头,即第0个元素的地址。

如果一个指针p指向一个数组arr[]的开头,那么p+i为数组第i个元素的地址,即&arr[i],那么*(p+i)为数组第i个元素的值,即arr[i]。

同理,若指针p指向数组的第n个元素,那么p+i为第n+1个元素的地址;不管 p 指向了数组的第几个元素,p+1 总是指向下一个元素,p-1 也总是指向上一个元素。

下面示例证实了这一点:

#include <stdio.h>

int main(void)
{
   int arr[] = {0, 1, 2, 3, 4};
   int *p = &arr[3];  //也可以写作 int *p = arr + 3;

   printf("%d, %d, %d, %d, %d\n", 
   *(p-3), *(p-2), *(p-1), *(p), *(p+1) );
   return 0;
}

运行结果为:

0, 1, 2, 3, 4

指针数组

指针数组:数组中每个元素都是指针。如:

int a=1,b=2,c=3;
int *arr[3] = {&a,&b,&c};

示例程序:

#include <stdio.h>
int main(void)
{
   int a = 1, b = 2, c = 3;
   //定义一个指针数组
   int *arr[3] = {&a, &b, &c};//也可以不指定长度,直接写作 int *parr[]
   //定义一个指向指针数组的指针
   int **parr = arr;
   printf("%d, %d, %d\n", *arr[0], *arr[1], *arr[2]);
   printf("%d, %d, %d\n", **(parr+0), **(parr+1), **(parr+2));

   return 0;
}

第一个 printf() 语句中,arr[i] 表示获取第 i 个元素的值,该元素是一个指针,还需要在前面增加一个 * 才能取得它指向的数据,也即 *arr[i] 的形式。

第二个 printf() 语句中,parr+i 表示第 i 个元素的地址,(parr+i) 表示获取第 i 个元素的值(该元素是一个指针),*(parr+i) 表示获取第 i 个元素指向的数据。

指针数组还可以和字符串数组结合使用,请看下面的例子:

#include <stdio.h>
int main(void)
{
   char *str[3] = 
 {
       "hello C",
       "hello C++",
       "hello Java"
   };
   printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
   return 0;
}

运行结果为:

hello C

hello C++

hello Java

二维数组指针

二维数组指针:指向二维数组的指针。如:

int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
int (*p)[4] = a;

a[3][4]表示一个3行4列的二维数组,其所有元素在内存中是连续存储的。

请看如下程序:

#include <stdio.h>
int main(void)
{
 int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
 int i,j;
 for( i = 0; i < 3; i++ )
 {
   for( j = 0; j < 4; j++ )
   {
     printf("a[%d][%d]=%d\n", i, j, &a[i][j]);
   }
 }

   return 0;
}

运行结果为:

a[0][0]=6422216

a[0][1]=6422220

a[0][2]=6422224

a[0][3]=6422228

a[1][0]=6422232

a[1][1]=6422236

a[1][2]=6422240

a[1][3]=6422244

a[2][0]=6422248

a[2][1]=6422252

a[2][2]=6422256

a[2][3]=6422260

可见,每个元素的地址都是相差4个字节,即每个连续在内存中是连续存储的。

按照以上定义可归纳出如下4个结论:

(1)p指向数组a的开头,也即第1行;p+1前进一行,指向第2行。

(2)*(p+1)表示取第2行元素(一整行元素)。

(3)*(p+1)+1表示第2行第2个元素的地址。

(4)((p+1)+1)表示第2行第2个元素的值。

综上4点,可得出如下结论:

a+i == p+i
 *(a+i) == *(p+i)
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j)== *(*(p+i)+j)

以上就是数组与指针常用的三种结合形式。


我的个人博客:https://zhengnianli.github.io/

我的微信公众号:嵌入式大杂烩

[](


 上一篇
【C语言笔记】数组与指针不等价 【C语言笔记】数组与指针不等价
前言数组与指针是不等价的,如: 数组名不可以改变,而指向数组的指针是可以改变的。 字符串指针指向的字符串中的字符是不能改变的,而字符数组中的字符是可以改变的。 求数组长度时,借用数组名可求得数组长度,而借用指针却得不到数组长度。
2018-10-25
下一篇 
【C语言笔记】指针变量的运算 【C语言笔记】指针变量的运算
前言指针变量也是可以进行运算的,如指针变量对其自身加上某个整数或减去某个整数,这在内存上体现为:相对这个指针向后偏移多少个单位或向前偏移了多少个单位,这里的单位与指针变量的类型有关。在32bit环境下,int类型占4个字节,float占4字
2018-10-22
  目录