- 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语言中一些重要的指针算术运算
- 指针的自增和自减
- 对指针加减整数
- 指针相减
- 指针的比较
让我们借助示例详细讨论所有这些指针算术运算。
指针的自增和自减
我们知道,“++”和“--”用作C语言中的自增和自减运算符。它们是一元运算符,以前缀或后缀方式与数字变量操作数一起使用,它们将变量的值增加或减少一。
假设在内存地址1000处创建一个整数变量“x”,其值为10。然后,“x++”将“x”的值设为11。
int x = 10; // created at address 1000 x++; // x becomes 11
如果我们将“y”声明为指向“x”的指针并将“y”增加1(使用“y++”)会发生什么?假设“y”本身的地址是2000。
int x = 10; // created at address 1000 // "y" is created at address 2000 // it holds 1000 (address of "x") int *y = &x ; y++; // y becomes 1004
由于变量“y”存储1000(“x”的地址),我们期望它由于“++”运算符而变为1001,但它增加了4,这是“int”变量的大小。
这是因为,如果“x”的地址是1000,则它占用4个字节:1000、1001、1002和1003。因此,下一个整数只能放在1004而不是之前。因此,当“y”(指向“x”的指针)增加时,“y”变为1004。
指针自增的示例
以下示例显示如何增加指针:
#include <stdio.h> int main(){ int x = 10; int *y = &x; printf("Value of y before increment: %d\n", y); y++; printf("Value of y after increment: %d", y); }
输出
运行代码并检查其输出:
Value of y before increment: 6422036 Value of y after increment: 6422040
您可以看到值增加了4。类似地,“--”运算符将值减少数据类型的大小。
指针自减的示例
让我们将“x”和“y”的类型更改为“double”和“float”,并查看自减运算符的效果。
#include <stdio.h> int main(){ double x = 10; double *y = &x; printf("value of y before decrement: %ld\n", y); y--; printf("value of y after decrement: %ld", y); }
输出
Value of y before decrement: 6422032 Value of y after decrement: 6422024
声明数组时,元素存储在相邻的内存位置。对于“int”数组,每个数组下标相隔4个字节,如下图所示:
因此,如果一个变量存储数组第0个元素的地址,则“自增”将其指向第1个元素。
通过增加指针遍历数组的示例
以下示例显示如何通过连续增加指针来遍历数组:
#include <stdio.h> int main(){ int a[]= {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; int len = sizeof(a)/sizeof(int); int *x = a; int i = 0; for(i = 0; i < len; i++){ printf("Address of subscript %d = %d Value = %d\n", i, x, *x); x++; } return 0; }
输出
运行代码并检查其输出:
Address of subscript 0 = 6421984 Value = 10 Address of subscript 1 = 6421988 Value = 20 Address of subscript 2 = 6421992 Value = 30 Address of subscript 3 = 6421996 Value = 40 Address of subscript 4 = 6422000 Value = 50 Address of subscript 5 = 6422004 Value = 60 Address of subscript 6 = 6422008 Value = 70 Address of subscript 7 = 6422012 Value = 80 Address of subscript 8 = 6422016 Value = 90 Address of subscript 9 = 6422020 Value = 100
对指针加减整数
可以向指针添加和减去整数值。当向指针添加整数时,指针指向下一个内存地址。类似地,当从指针中减去整数时,指针指向前面的内存位置。
对指针加减整数不会直接将该值加到或减去指针,而是会将该值乘以数据类型的大小后加到或减去指针。
例如,有一个整数指针变量ptr,它指向地址123400,如果将1加到ptr(ptr+1),它将指向地址123404(整数大小为4)。
让我们评估一下:
ptr = 123400 ptr = ptr + 1 ptr = ptr + sizeof(int)*1 ptr = 123400 + 4 ptr = 123404
向指针添加值的示例
在下面的示例中,我们声明一个数组和指向数组的指针。用数组的第一个元素初始化指针,然后向指针添加一个整数值(2)以获取数组的第三个元素。
#include <stdio.h> int main() { int int_arr[] = {12, 23, 45, 67, 89}; int *ptrArr = int_arr; printf("Value at ptrArr: %d\n", *ptrArr); // Adding 2 in ptrArr ptrArr = ptrArr + 2; printf("Value at ptrArr after adding 2: %d\n", *ptrArr); return 0; }
输出
Value at ptrArr: 12 Value at ptrArr after adding 2: 45
从指针减去值的示例
在下面的示例中,我们声明一个数组和指向数组的指针。用数组的最后一个元素初始化指针,然后从指针减去一个整数值(2)以获取数组的第三个元素。
#include <stdio.h> int main() { int int_arr[] = {12, 23, 45, 67, 89}; int *ptrArr = &int_arr[4]; // points to last element printf("Value at ptrArr: %d\n", *ptrArr); // Subtracting 2 in ptrArr ptrArr = ptrArr - 2; printf("Value at ptrArr after adding 2: %d\n", *ptrArr); return 0; }
输出
Value at ptrArr: 89 Value at ptrArr after adding 2: 45
指针相减
我们熟悉“+”和“−”运算符在用作常规数字操作数时的用法。但是,当您将这些运算符与指针一起使用时,它们的行为略有不同。
由于指针是相当大的整数(尤其是在现代64位系统中),因此两个指针的加法没有意义。当我们将1加到指针时,它指向下一个可能存储整数的位置。显然,当我们添加一个指针(它本身是一个很大的整数)时,它指向的位置可能不在内存布局中。
但是,两个指针的减法是现实的。它返回可以容纳在两个指针中的数据类型数量。
两个指针相减的示例
让我们以前面示例中的数组为例,执行a[0]和a[9]指针的减法
#include <stdio.h> int main(){ int a[]= {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; int *x = &a[0]; // zeroth element int *y = &a[9]; // last element printf("Add of a[0]: %ld add of a[9]: %ld\n", x, y); printf("Subtraction of two pointers: %ld", y-x); }
输出
运行代码并检查其输出:
Add of a[0]: 140729162482768 add of a[9]: 140729162482804 Subtraction of two pointers: 9
可以看出,这两个整数之间的数值差是36;这表明减法结果是9,因为在两个指针之间可以容纳9个整数。
指针的比较
可以使用关系运算符(例如“==”、“<”和“>”)来比较指针。如果“p1”和“p2”指向彼此相关的变量(例如同一数组的元素),则可以有意义地比较“p1”和“p2”。
比较指针的示例
在下面的示例中,我们声明两个指针,并分别用数组的第一个和最后一个元素初始化它们。我们将不断增加第一个变量指针,只要它指向的地址小于或等于数组最后一个元素的地址,“&var[MAX − 1]”(即第二个指针)。
#include <stdio.h> const int MAX = 3; int main() { int var[] = {10, 100, 200}; int i, *ptr1, *ptr2; // Initializing pointers ptr1 = var; ptr2 = &var[MAX - 1]; while (ptr1 <= ptr2) { printf("Address of var[%d] = %p\n", i, ptr1); printf("Value of var[%d] = %d\n", i, *ptr1); /* point to the previous location */ ptr1++; i++; } return 0; }
输出
运行代码并检查其输出:
Address of var[0] = 0x7ffe7101498c Value of var[0] = 10 Address of var[1] = 0x7ffe71014990 Value of var[1] = 100 Address of var[2] = 0x7ffe71014994 Value of var[2] = 200