C 语言编程教程

C 语言 - 首页

C 语言基础

C 语言 - 概述 C 语言 - 特性 C 语言 - 发展历史 C 语言 - 环境设置 C 语言 - 程序结构 C 语言 - Hello World C - 编译过程 C - 注释 C - 标记 C - 关键字 C - 标识符 C - 用户输入 C - 基本语法 C - 数据类型 C - 变量 C - 整数提升 C - 类型转换 C - 类型转换 C - 布尔值

C 语言中的常量和文字

C - 常量 C - 字面量 C - 转义序列 C - 格式说明符

C 语言中的运算符

C - 运算符 C - 算术运算符 C - 关系运算符 C - 逻辑运算符 C - 位运算符 C - 赋值运算符 C - 一元运算符 C - 递增和递减运算符 C - 三元运算符 C - sizeof 运算符 C - 运算符优先级 C - 其他运算符

C 语言中的决策

C - 决策 C - if 语句 C - if...else 语句 C - 嵌套 if 语句 C - switch 语句 C - 嵌套 switch 语句

C 语言中的循环

C - 循环 C - While 循环 C - For 循环 C - Do...while 循环 C - 嵌套循环 C - 无限循环 C - Break 语句 C - Continue 语句 C - goto 语句

C 语言中的函数

C - 函数 C - Main 函数 C - 按值调用函数 C - 按引用调用函数 C - 嵌套函数 C - 可变参数函数 C - 用户定义函数 C - 回调函数 C - return 语句 C - 递归

C 语言中的作用域规则

C - 作用域规则 C - 静态变量 C - 全局变量

C 语言中的数组

C - 数组 C - 数组的属性 C - 多维数组 C - 将数组传递给函数 C - 从函数返回数组 C - 可变长度数组

C 语言中的指针

C - 指针 C - 指针和数组 C - 指针的应用 C - 指针运算 C - 指针数组 C - 指向指针的指针 C - 将指针传递给函数 C - 从函数返回指针 C - 函数指针 C - 指向数组的指针 C - 指向结构体的指针 C - 指针链 C - 指针 vs 数组 C - 字符指针和函数 C - NULL 指针 C - void 指针 C - 悬垂指针 C - 解引用指针 C - Near、Far 和 Huge 指针 C - 指针数组的初始化 C - 指针与多维数组

C 语言中的字符串

C - 字符串 C - 字符串数组 C - 特殊字符

C 语言的结构体和联合

C - 结构体 C - 结构体和函数 C - 结构体数组 C - 自引用结构 C - 查找表 C - 点 (.) 运算符 C - 枚举(或 enum) C - 结构填充和打包 C - 嵌套结构 C - 匿名结构和联合 C - 联合 C - Bit 位字段 C - Typedef

C 语言中的文件处理

C - 输入和输出 C - 文件 I/O(文件处理)

C 语言中的预处理器

C - 预处理器 C - #pragma 编译指示 C - 预处理器操作符 C - 宏 C - 头文件

C 语言中的内存管理

C - 内存管理 C - 内存地址 C - 存储类

C 其他主题

C - 错误处理 C - 可变参数 C - 命令执行 C - 数学函数 C - static 静态关键字 C - 随机数生成 C - 命令行参数

C 语言编程资源

C语言问题与解答答案 C语言快速指南 C语言速查表 C语言实用资源 C语言讨论


C 语言中的指针和数组

在 C 语言编程中,数组和指针的概念非常重要。两者之间也存在着密切的联系。本章将详细讲解 C 语言编程中数组和指针之间的关系。

C 语言中的数组

C 语言中的数组是存储在连续内存块中的同质元素集合,这些元素属于同一数据类型。数组的大小是方括号内的整数,位于数组名称的前面。

声明数组

声明数组的语法如下:语法

data_type arr_name[size];

数组中的每个元素都由一个唯一的递增索引标识,索引从"0"开始。数组可以通过多种方式声明和初始化。

您可以声明一个数组,然后在代码中根据需要初始化它。例如

int arr[5];
... 
... 
a[0] = 1;
a[1] = 2;
... 
... 

您也可以同时声明和初始化数组。要存储的值将以逗号分隔的列表形式放在花括号内。

int a[5] = {1, 2, 3, 4, 5};

注意:在声明时初始化数组时,指定其大小是可选的,因为编译器会自动计算大小。因此,以下语句也有效 -

int a[] = {1, 2, 3, 4, 5};

示例:数组的下限和上限

数组中的所有元素都有一个位置索引,从"0"开始。数组的下界始终为"0",而上限为"size - 1"。我们可以利用此属性,使用循环遍历、赋值或读取数组下标中的输入。

请看以下示例 -

#include <stdio.h>

int main(){

   int a[5], i;
   
   for(i = 0; i <= 4; i++){
      scanf("%d", &a[i]);
   }

   for(i = 0; i <= 4; i++){
      printf("a[%d] = %d
",i,  a[i]);
   }
   
   return 0;
}

输出

运行代码并检查其输出 −

a[0] = 712952649
a[1] = 32765
a[2] = 100
a[3] = 0
a[4] = 4096

C 语言中的指针

指针是存储另一个变量地址的变量。在 C 语言中,符号 (&) 用作 取地址运算符。该运算符的返回值将赋值给指针。

要将变量声明为指针,需要在变量名称前添加星号 (*)。此外,指针变量的类型必须与其存储地址的变量类型相同。

在此代码片段中,"b" 是一个整型指针,用于存储整型变量 "a" 的地址 -

int a = 5;
int *b = &a;

对于数组,你可以将其第 0 个元素的地址赋值给指针。

int arr[] = {1, 2, 3, 4, 5};
int *b = &arr[0];

在 C 语言中,数组本身的名称解析为其第 0 个元素的地址。这意味着,在上面的例子中,我们可以使用 "arr" 等同于 "&[0]":

int *b = arr;

示例:指针的增量运算符

与普通数值变量不同(其中增量运算符"++"将其值增加 1),指针使用的增量运算符会将其值增加其数据类型的 sizeof 个值。

因此,int 指针在增量时会增加 4。

#include <stdio.h>

int main(){

   int a = 5;
   int *b = &a;
   
   printf("Address of a: %d
", b);
   b++;
   printf("After increment, Address of a: %d
", b);
   
   return 0;
}

输出

运行代码并检查其输出 −

Address of a: 6422036
After increment, Address of a: 6422040

C 语言中的解引用运算符

在 C 语言中,符号"*"用作解引用运算符。它返回指针指向的地址所存储的值。

因此,以下语句返回"5",即变量"a"所存储的值,该变量是"b"所指向的变量。

int a = 5;
int *b = &a;
printf("value of a: %d
", *b);

注意:如果是 char 指针,它将自增 1;如果是 double 指针,它将自增 8;如果是结构体类型,则以该结构体类型的sizeof 值为增量。

示例:使用指针遍历数组

我们可以利用指针的这一属性,借助指针遍历数组元素。

#include <stdio.h>

int main(){
    
   int arr[5] = {1, 2, 3, 4, 5};
   int *b = arr;

   printf("Address of a[0]: %d value at a[0] : %d
",b, *b);
    
   b++;
   printf("Address of a[1]: %d value at a[1] : %d
", b, *b);

   b++;
   printf("Address of a[2]: %d value at a[2] : %d
", b, *b);

   b++;
   printf("Address of a[3]: %d value at a[3] : %d
", b, *b);
    
   b++;
   printf("Address of a[4]: %d value at a[4] : %d
", b, *b);

   return 0;
}

输出

运行代码并检查其输出 −

address of a[0]: 6422016 value at a[0] : 1
address of a[1]: 6422020 value at a[1] : 2
address of a[2]: 6422024 value at a[2] : 3
address of a[3]: 6422028 value at a[3] : 4
address of a[4]: 6422032 value at a[4] : 5

注意事项

需要注意的是:-

  • "&arr[0]" 等同于 "b",而 "arr[0]" 等同于 "*b"。
  • 同样,"&arr[1]" 等同于 "b + 1",而 "arr[1]" 等同于 "*(b + 1)"。
  • 此外,"&arr[2]" 等同于 "b + 2",而 "arr[2]" 等同于 "*(b+2)"。
  • 一般而言, "&arr[i]" 等同于 "b + I",而 "arr[i]" 等同于 "*(b+i)"。

示例:使用解引用运算符遍历数组

我们可以使用此属性,并使用循环通过解引用运算符

来遍历数组。
#include <stdio.h>

int main(){

   int arr[5] = {1, 2, 3, 4, 5};
   int *b = arr;
   int i;

   for(i = 0; i <= 4; i++){
      printf("a[%d] = %d
",i,  *(b+i));
   }
   
   return 0;
}

输出

运行代码并检查其输出 −

a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5

您还可以在每次迭代中增加指针并获得相同的结果 -

for(i = 0; i <= 4; i++){
   printf("a[%d] = %d
", i, *b);
   b++;
}

C 语言中的数组和指针概念密切相关。您可以使用指针来提高程序的效率,因为指针直接处理内存地址。指针也可以用来处理多维数组。