指针的运算 详解
指针的运算
指针加减 常量
请看下面的程序,猜测一下结果:
int main() {
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int* a = &arr;
printf("a = %p\n", a); printf("a + 1 = %p\n", a + 1); printf("a - 1 = %p\n", a - 1);
}
|
运行结果:
a = 00AFF82C a + 1 = 00AFF830 a - 1 = 00AFF828
|
可以看到, a 与 a + 1 和 a - 1 都差了四个字节
指针加减常量 加减的大小为 sizeof(类型) * 常量
再试试 char 类型?
int main() {
char arr[10] = { ' 1', '2', '3', '4', '5', '6', '7', '8', '9', '10',}; char* a = &arr;
printf("a = %p\n", a); printf("a + 1 = %p\n", a + 1); printf("a - 1 = %p\n", a - 1);
}
|
结果如我们所料:
a = 0095F9E0 a + 1 = 0095F9E1 a - 1 = 0095F9DF
|
相差大小 为 1
指针 - 指针
先来看一段程序吧:
int main() {
char arr1[10] = { ' 1', '2', '3', '4', '5', '6', '7', '8', '9', '10', }; int arr2[5] = { 1, 2, 3, 4, 5 };
char* ch1 = &arr1[4]; char* ch2 = &arr1; int* i1 = &arr2[4]; int* i2 = &arr2;
printf("ch1 - ch2 = %d\n", ch1 - ch2); printf("ch2 - ch1 = %d\n", ch2 - ch1); printf("\ni1 - i2 = %d\n", i1 - i2); printf("i2 - i1 = %d\n", i2 - i1); }
|
指针相减 结果会是 指针相差的大小吗?看结果:
ch1 - ch2 = 4 ch2 - ch1 = -4
i1 - i2 = 4 i2 - i1 = -4
|
指针 减 指针 意义是 两个地址之间相隔的单元格数
也可以理解为:指针相差的大小 / sizeof(类型)
如果想输出两个指针 相差的距离(大小)只需要将变量类型 更改成普通类型,如下:
int main() {
char arr1[10] = { ' 1', '2', '3', '4', '5', '6', '7', '8', '9', '10', }; int arr2[5] = { 1, 2, 3, 4, 5 }; char ch1 = &arr1[4]; char ch2 = &arr1; int i1 = &arr2[4]; int i2 = &arr2;
printf("ch1 - ch2 = %d\n", ch1 - ch2); printf("ch2 - ch1 = %d\n", ch2 - ch1); printf("\n"); printf("i1 - i2 = %d\n", i1 - i2); printf("i2 - i1 = %d\n", i2 - i1); }
|
输出结果:
ch1 - ch2 = 4 ch2 - ch1 = -4
i1 - i2 = 16 i2 - i1 = -16
|
普通类型是无法进行解引用操作的
总结一下
指针 可以 加减常数,指针之间可以相减,可以比较(如:> == < >=等)
但是指针不能乘除,相加 这是没有意义的
举个很简单的例子,时间可以相减,但是时间乘除或者相加有什么意义呢?
NULL
通过前面的学习,我们知道:内存中的地址有很多编号。如果你的机器是 32 位,
那么内存范围是:0 ~ 2^32 -1
(32位2进制数全1) 最大值大约为 4GB
NULL其实就表示 0地址
补充个小知识点:
1kB=1024B =2^10(次方是二进制形式)
1MB=1024kB =2^20
1GB=1024MB =2^30
1TB=1024GB =2^40
NULL有什么用?
0地址规定为我们不能写入的地址,你的指针不指向 0地址,如果你的指针指向了 0地址 那么程序运行时会崩溃。基于这个特点,0地址 也就是NULL有了很重要的功能:
NULL类型时 void * 可以设置任何类型为NULL
下面的程序是官网上讲NULL时给出的例子:
#include <stdlib.h> #include <stdio.h> int main(void) { int* p = NULL; struct S* s = NULL; void(*f)(int, double) = NULL;
char* ptr = malloc(10); if (ptr == NULL) printf("Out of memory"); free(ptr); }
|
void*
void* 表示 不知道指向什么类型的 指针
比如:
int i = 1; int* p = &i; void* q = (void*)p;
|
这么写并没有改变 p 所指向的变量的类型, 而是可以让程序用不同的眼光通过 p看它所指的变量。
指针类型的作用
- 指针的类型决定了指针向前或者向后走一步有多大
- 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)
(具体示例参考 C语言复习巩固(五) 指针(初阶))
更多关于指针的可以参考我的其他篇文章:
C语言复习巩固(五) 指针(初阶)
指针运算详解,const详解,NULL?void* 指针基础