- 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语言 - 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语言 - 指针与数组
- 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语言中初始化指针数组?
在声明时,可以通过为指针变量赋值现有变量的地址来初始化它。以下代码片段显示了如何初始化一个指针:
int x = 10; int *y = &x;
默认情况下,所有变量(包括指针变量)都属于“自动存储类别”。这意味着指针变量将存储一个不可预测的、垃圾的、随机的内存地址,这可能导致未定义的行为和潜在的程序风险,例如分段错误。因此,如果我们在声明时没有特定的值要存储,则应将其初始化为 NULL。
int *ptr = NULL;
“指针数组”在每个元素中存储地址。数组的类型必须与目标变量的类型匹配。
使用 static 关键字初始化指针数组
您还可以使用static关键字初始化指针数组,以在每个下标中存储“0”。
示例
#include <stdio.h> int main(){ static int *ptr[5]; for (int i = 0; i < 5; i++){ printf("ptr[%d] = %d\n", i, ptr[i]); } return 0; }
输出
运行代码并检查其输出:
ptr[0]= 0 ptr[1]= 0 ptr[2]= 0 ptr[3]= 0 ptr[4]= 0
初始化整数指针数组
在这里,我们声明一个整数指针数组,并存储三个整数变量的地址。
示例
#include <stdio.h> int main(){ int a = 10, b = 20, c = 30; int *ptr[3] = {&a, &b, &c}; for (int i = 0; i < 3; i++){ printf("ptr[%d]: address: %d value: %d\n", i, ptr[i], *ptr[i]); } return 0; }
输出
运行代码并检查其输出:
ptr[0]: address: 6422040 value: 10 ptr[1]: address: 6422036 value: 20 ptr[2]: address: 6422032 value: 30
通过直接地址初始化指针数组
我们可以将普通数组的每个元素的地址存储在指针数组的相应元素中。
示例
#include <stdio.h> int main(){ int arr[] = {10, 20, 30}; int *ptr[3] = {&arr[0], &arr[1], &arr[2]}; for (int i = 0; i < 3; i++){ printf("ptr[%d]: address: %d value: %d\n", i, ptr[i], *ptr[i]); } return 0; }
输出
运行代码并检查其输出:
ptr[0]: address: 6422032 value: 10 ptr[1]: address: 6422036 value: 20 ptr[2]: address: 6422040 value: 30
使用基地址遍历数组
当我们获得数组的基地址(在本例中为“&arr[0]”)时,我们可以知道指针会根据数据类型的尺寸递增,从而获得其后续元素的地址。
因此,只需使用基地址(数组名与第 0 个元素的地址相同),我们就可以遍历数组。
示例 1
看看下面的例子:
#include <stdio.h> int main(){ int arr[] = {10, 20, 30}; int *ptr=arr; for (int i = 0; i < 3; i++){ printf("ptr[%d]: address: %d value: %d\n", i,ptr+i, *(ptr+i)); } return 0; }
输出
运行代码并检查其输出:
ptr[0]: address: 6422020 value: 10 ptr[1]: address: 6422024 value: 20 ptr[2]: address: 6422028 value: 30
示例 2:使用指针数组遍历二维数组
在这个例子中,我们有一个二维数组。每一行的第 0 个元素的地址都存储在一个指针数组中。遍历时,指针数组中每个元素存储的地址(指向对应行的第 0 个元素)都会递增,以获取每一行中的值。
#include <stdio.h> int main(){ // 2d array int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, }; int ROWS = 2, COLS = 4; int i, j; // pointer int (*ptr)[4] = arr; // print the element of the array via pointer ptr for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { printf("%d ", *(ptr[i]+j)); } printf("\n"); } return 0; }
输出
运行此代码时,将产生以下输出:
1 2 3 4 5 6 7 8
示例 3
这里我们实际上并不需要指针数组,因为我们可以使用这个二维数组的名称作为它的基指针,并逐行逐列地递增它来获取给定二维数组中的元素:
#include <stdio.h> int main(){ // 2d array int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, }; int ROWS = 2, COLS = 4; int i, j; // pointer int *ptr = arr; // print the element of the array via pointer ptr for (i = 0; i < ROWS; i++){ for (j = 0; j < COLS; j++){ printf("%d ", *(ptr + i * COLS + j)); } printf("\n"); } return 0; }
输出
输出与之前的代码类似:
1 2 3 4 5 6 7 8
初始化字符指针数组(字符串)
在 C 编程中,字符串是 char 数据类型的数组。由于数组的名称也表示其第 0 个元素的地址,因此可以声明一个字符串为:
char arr[] = "Hello";
使用指针表示法,字符串被赋值给 char 指针为:
char *arr = "Hello";
然后,我们可以声明一个 char 指针数组来存储多个字符串,如下所示:
char *arr[3] = {"string1", "string2", "string3", . . . };
示例
下面的例子有一个char 指针数组,用于存储计算机语言的名称:
#include <stdio.h> int main(){ char *langs [10] = { "PYTHON", "JAVASCRIPT", "PHP", "NODE JS", "HTML", "KOTLIN", "C++", "REACT JS", "RUST", "VBSCRIPT" }; for(int i = 0; i < 10; i++) printf("%s\n", langs[i]); return 0; }
输出
运行此代码时,将产生以下输出:
PYTHON JAVASCRIPT PHP NODE JS HTML KOTLIN C++ REACT JS RUST VBSCRIPT
在这个程序中,“langs”是一个指向包含 10 个字符串的数组的指针。因此,如果“langs[0]”指向地址 5000,“langs + 1”将指向地址 5004,该地址存储指向第二个字符串的指针。
因此,我们也可以使用以下循环变体来打印字符串数组:
for (int i = 0; i < 10; i++){ printf("%s\n", *(langs + i)); }
动态指针数组的初始化
您可以使用malloc() 函数以动态方式声明和初始化指针数组。
示例
看看下面的例子:
#include <stdio.h> int main(){ int *arr = (int *)malloc (sizeof (int) * 5); for(int i = 0; i < 5; i++){ arr[i] = i; } for (int x = 0; x < 5; x++){ printf("%d %d\n", x, arr[x]); } return 0; }
输出
运行此代码时,将产生以下输出:
0 0 1 1 2 2 3 3 4 4
您甚至可以请求用户输入并将值赋给指针数组中的元素:
for(i = 0; i < 5; i++){ scanf("%d", &x); arr[i] = x; }