- 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语言 - 主函数
- 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语言 - 函数指针
- C语言 - 指向数组的指针
- C语言 - 指向结构体的指针
- C语言 - 指针链
- C语言 - 指针与数组的区别
- C语言 - 字符指针和函数
- C语言 - 空指针
- C语言 - void指针
- C语言 - 悬空指针
- C语言 - 解引用指针
- C语言 - 近指针、远指针和巨大指针
- C语言 - 指针数组的初始化
- C语言 - 指针与多维数组的比较
- C语言中的字符串
- C语言 - 字符串
- C语言 - 字符串数组
- C语言 - 特殊字符
- C语言中的结构体和联合体
- C语言 - 结构体
- C语言 - 结构体和函数
- C语言 - 结构体数组
- C语言 - 自引用结构体
- C语言 - 查找表
- C语言 - 点(.)运算符
- C语言 - 枚举 (enum)
- C语言 - 结构体填充和打包
- C语言 - 嵌套结构体
- C语言 - 匿名结构体和联合体
- C语言 - 联合体
- C语言 - 位域
- C语言 - typedef
- C语言中的文件处理
- C语言 - 输入输出
- C语言 - 文件I/O (文件处理)
- C语言预处理器
- C语言 - 预处理器
- 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”,而上界为“大小 - 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\n",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”作为“&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\n", b); b++; printf("After increment, Address of a: %d\n", b); return 0; }
输出
运行代码并检查其输出:
Address of a: 6422036 After increment, Address of a: 6422040
C语言中的解引用运算符
在C语言中,"*"符号用作解引用运算符。它返回指针指向的地址中存储的值。
因此,以下语句返回“5”,这是变量“a”中存储的值,变量“b”指向“a”。
int a = 5; int *b = &a; printf("value of a: %d\n", *b);
注意:对于char指针,它将递增1;对于double指针,它将递增8;对于struct类型,它将递增该struct类型的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\n",b, *b); b++; printf("Address of a[1]: %d value at a[1] : %d\n", b, *b); b++; printf("Address of a[2]: %d value at a[2] : %d\n", b, *b); b++; printf("Address of a[3]: %d value at a[3] : %d\n", b, *b); b++; printf("Address of a[4]: %d value at a[4] : %d\n", 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\n",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\n", i, *b); b++; }
C语言中数组和指针的概念密切相关。可以使用指针来提高程序的效率,因为指针直接处理内存地址。指针也可以用来处理多维数组。