再议 C 语言中的指针与数组(4)

简介: 再议 C 语言中的指针与数组(4) 一 概述 前面的文章中,回顾了 C 语言中的指针,对指针有了一个比较初步的了解。在本文中,结合数组,再次对指针进行回顾。 二 数组与指针 在 C 语言中,指向数组的指针是比较常见的,也是非常方便和适用的。

再议 C 语言中的指针与数组(4)

一 概述

前面的文章中,回顾了 C 语言中的指针,对指针有了一个比较初步的了解。在本文中,结合数组,再次对指针进行回顾。

二 数组与指针

在 C 语言中,指向数组的指针是比较常见的,也是非常方便和适用的。

2.1 指向数组的指针

# include<stdio.h>

int main(int argc,char *argv[]){
  int a[10] = {1,2,3,4,6,5,7,8,9,0};
  int *p;
  // p = a;
  p = &a[0];
  for (int i = 0; i < 10; i++){
    printf("%d\t",*p);
    p++;
  }
  return 0;
}
// 1       2       3       4       6       5       7       8       9       0
AI 代码解读

本例中,指针变量 p 指向了数组 a[10],并演示了通过指针遍历数组的常规方法。 我们可以直接通过数组名直接将指针指向该数组的第一个元素,“p = a;” 和 “p = &a[10];”这两行代码在本质上是等价的。需要注意的是:通过这种方式使指针指向整个数组,数组名前面不能再使用运算符 &。 若指针指向数组的某一元素,运算符 & 不能省略。

2.2 指向复合常量的指针

# include<stdio.h>

int main(int argc,char *argv[]){
  int *p = (int []){1,2,3,4,6,5,7,8,9,0};
  for (int i = 0; i < 10; i++){
    printf("%d\t",*p);
    p++;
  }
  return 0;
}
//1       2       3       4       6       5       7       8       9       0
AI 代码解读

本例声明并初始化了一个没有名称的数组。 通过这种方式,我们不需要先声明一个数组,然后再用指针指向数组的第一个元素。 在某些场景中,这个特性使用起来比较方便。 这是 C99 的一个特性。 另外, 在本例的 for 循环体,声明并初始化了 i, 这也是 C99 的一个特性,需要注意一下。

可以声明匿名数组的长度。

# include<stdio.h>

int main(int argc,char *argv[]){
  int *p = (int [10]){1,2,3,4,6,5,7,8,9,0};
  for (int i = 0; i < 10; i++){
    printf("%d\t",*p);
    p++;
  }
  return 0;
}
AI 代码解读

2.3 通过指针对数组进行操作

通过指针也可以很方便、高效地对数组进行操作,请看以下例子:

# include<stdio.h>
# define N 10

int main(int argc,char *argv[]){
  int a[N];
  int *p;
  for (p = a; p < a + N; p++){
    printf("Please input a[%d]:",p - a);
    scanf("%d",p);
  }
    for (p = a; p < a + N; p++){
    printf("a[%d] = %d;\t ", p - a, *p);
  }
  printf("\n");
  return 0;
}
/*
Please input a[0]:1
Please input a[1]:2
Please input a[2]:3
Please input a[3]:4
Please input a[4]:5
Please input a[5]:66
Please input a[6]:7
Please input a[7]:7
Please input a[8]:8
Please input a[9]:9
a[0] = 1;        a[1] = 2;       a[2] = 3;       a[3] = 4;       a[4] = 5;       a[5] = 66;      a[6] = 7;       a[7] = 7;       a[8] = 8;       a[9] = 9;
*/
AI 代码解读

这个例子展示了通过操作指针对数组进行赋值,并通过指针的移动完成对数组的遍历。例子中使用了两个指针相减的方式确定了数组下标。使用指针操作对数组进行赋值或遍历的过程中,在操作开始之前需要将指针复位,指向数组的第一个元素。这个操作必不可少,否则将出错。

2.4 指针与数组在函数定义中的使用

在函数定义时,数组可以使用指针或显示声明来定义形式参数。

# include<stdio.h>

int main(int argc,char *argv[]){
  unsigned int array[] = {3,5,6,7,1,2,0}, len;
  int find_max(unsigned int [], int n);
  len = sizeof array / sizeof array[0];
  printf("%d\n",find_max(array,len));
  return 0;
}

int find_max(unsigned int a[], int n){
  int max = 0;
  for (int i = 0; i < n; i++){
    if ( a[i] > max)
       max = a[i];
  }
  return max;
}
// 7
AI 代码解读

# include<stdio.h>

int main(int argc,char *argv[]){
  unsigned int array[] = {3,5,6,7,1,2,0}, len;
  int find_max(unsigned int [], int n);
// int find_max(unsigned int *, int n);
  len = sizeof array / sizeof array[0];
  printf("%d\n",find_max(array,len));
  return 0;
}

int find_max(unsigned int *a, int n){
  int max = 0;
  for (int i = 0; i < n; i++){
    if ( a[i] > max)
       max = a[i];
  }
  return max;
}
// 7
AI 代码解读

在以上2段代码中,写法不一样,但执行效果却一致。事实上数组作为形参时,是以指针进行传递的。也就是说,对于形参而言,声明为数组与声明为指针是一样的,但是对于变量来说,声明为数组与声明为指针是不一样的。指定长度的数组会导致编译器预留指定数据类型长度的空间,申明为指针会导致编译器为指针变量分配空间。

2.5 多维数组与指针

使用指针遍历多维数组:

# include<stdio.h>

int main(int argc,char *argv[]){
  int *p, array[2][3] = {{12,43,11},{10,56,89}};
  for (p = &array[0][0]; p <= &array[1][2]; p++)
    printf("array[%d][%d]: %d\n",(p - &array[0][0])/3, (p - &array[0][0])%3, *p);
  return 0;
}
/*
array[0][0]: 12
array[0][1]: 43
array[0][2]: 11
array[1][0]: 10
array[1][1]: 56
array[1][2]: 89
*/
AI 代码解读

以上代码等价于:

# include<stdio.h>

int main(int argc,char *argv[]){
  int *p, array[2][3] = {{12,43,11},{10,56,89}};
  for (p = array[0]; p <= &array[1][2]; p++)
    printf("array[%d][%d]: %d\n",(p - &array[0][0])/3, (p - &array[0][0])%3, *p);
  return 0;
}
AI 代码解读

对比以上两端代码,乍一看,并没有什么差异!举着个例子的重点在第四行的 “p = &array0” 和 “p = array[0]”。通过这两行代码,不难看出:二维数组中,指针 p 不是指向 array0 的指针,而是指向 array[0] 的指针。

多维数组是不能以数组名直接作为指针指向的对象,需要稍微做一些调整才能使用数组名作为指针。在 C 语言中,多维数组实际上就是以一维数组来进行处理的。结合上面的例子,C 语言把 array 当作一维数组来进行处理,而这个一维数组的美一个元素又是一个一维数组。由此,可以推广到多维数组。

那么,在多维数组内是否可以直接以数组名为作为指针呢?请看以下例子:

# include<stdio.h>
# define ROWS 2
# define COLS 3

int main(int argc,char *argv[]){
  int *p, array[ROWS][COLS] = {{12,43,11},{10,56,89}};
    for (p = *array; p < *array + (ROWS * COLS); p++)
      printf("array[%d][%d]: %d\n",(p - *array) / COLS, (p - *array) % COLS, *p);
  return 0;
}
/*
array[0][0]: 12
array[0][1]: 43
array[0][2]: 11
array[1][0]: 10
array[1][1]: 56
array[1][2]: 89
*/
AI 代码解读

在这一代码片段中,将指针变量 p 指向一个指针类型的数组。也就是说,指针变量 p 指向了一个数组,这个数组的全部元素均为指针。简而言之,指针变量 p 是指向指针数组的指针。

三 总结

3.1 在 C 语言中,指针与数组关系密切,既有联系又有区别。在实际的使用过程中要特别谨慎。

3.2 指针是 C 语言中的精华。作为一名 C 语言学习者,指针虽然比较坑,但是这个是无法逃避的,必须花大量的时间与精力去学习与理解。

3.3 指针常常会与数组发生关联,对指针的理解必须透彻。

3.4 鉴于笔者水平,文中可能存在若干谬误,希望大家能帮忙指出,谢谢!

相关文章
一文彻底搞明白C语言的数组
本文详细介绍了C语言中的数组,包括定义、初始化(静态与动态)、存储方式、访问方法及常用操作,如遍历、修改元素和作为函数参数传递。数组是C语言中最基本的数据结构之一,掌握它对编程至关重要。下篇将介绍二维数组,敬请期待!
252 0
一文彻底搞明白C语言的数组
一文轻松拿捏C语言的指针的基础使用
本文介绍了C语言中的指针概念,包括直接访问和间接访问内存的方式、指针变量的定义与使用、取址运算符`&`和取值运算符`*`的应用,帮助读者深入理解指针这一C语言的核心概念。君志所向,一往无前!
111 0
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
276 7
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
858 9
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
188 7
【C语言】两个数组比较详解
比较两个数组在C语言中有多种实现方法,选择合适的方法取决于具体的应用场景和性能要求。从逐元素比较到使用`memcmp`函数,再到指针优化,每种方法都有其优点和适用范围。在嵌入式系统中,考虑性能和资源限制尤为重要。通过合理选择和优化,可以有效提高程序的运行效率和可靠性。
497 6
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
191 5
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
511 3
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问