【C语言指针专题(2)】指针的运算

一、const修饰指针

1.const修饰变量

我们知道变量的值是可以随时进行赋值改变的,而当一个变量被const修饰时呢?

//演示1.1.1

#include <stdio.h>

int main()
{
    int num1 = 0;
    num1 = 10;            // num1 是可以被修改的
    printf("%d\n", num1);
    const int num2 = 0;
    num2 = 20;            // num2 不可以被修改
    printf("%d\n", num2);
    return 0;
}
    

这里num1是可以被修改并打印的,但是num2是被const修饰的变量,不可更改,对它进行赋值会导致程序报错。

然而我们也不是就完全没办法改变num2中的值了。运用指针指向num2再进行解引用,就可以对num2中的值进行修改。

这里的目的只是介绍这样一个知识点,但平时编程时并不建议这样做,因为这样实际是在破坏语法规则。

//演示1.1.2

#include <stdio.h>

int main()
{
    int num1 = 0;
    num1 = 10;
    printf("%d\n", num1);
    const int num2 = 0;
    int* pn = &num2;
    *pn = 20;
    printf("%d\n", *pn);
    return 0;
}

2.const修饰指针

2.1. const在 * 左边

const在 * 左边时,限制的是*pa,即使指针变量pa指向的变量a,不能通过指针pa进行更改。

//演示1.2.1

#include <stdio.h>

int main()
{
	int a = 2, b = 4;
	const int* pa = &a;
	a = 6;        //①
	pa = &b;      //②
	*pa = 8;      //③
	return 0;
}

①可修改,因为a是变量,且没有被const修饰

②可修改,因为const修饰的是*pa而没有限制pa

③不可修改,因为*pa被const修饰,不可更改

2.2. const在 * 右边

const在 * 右边时,限制的是pa,即指针变量pa指向的对象不可以再改变。

还是演示1.2.1中的代码,再看①②③的情况:

①可修改

②不可修改,因为pa被const所限制,指针pa指向的对象是不能变的,只能指向变量a

③可修改,因为*pa并没有受const限制

2.3. const在 * 两边都有

这种情况下,pa和*pa都会受到限制,也就是说,同样在演示1.2.1的代码中,②和③都是不可修改,无法实现的。

二、指针运算

指针的的基本运算有三种,分别是:指针+-整数、指针+-指针、指针的关系运算。

1.指针+-整数

因为数组在内存中是连续存放的,所以只要知道第⼀个元素的地址,顺藤摸瓜就能找到后面的所有元素。

//演示2.1.1

int main()
{
    int arr = { 1,2,3,4,5,6,7,8,9,10 };
    return 0;
}

于是就有下面这段演示代码:

//演示2.1.2

include <stdio.h>

int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 for(i=0; i<sz; i++)
 {
 printf("%d ", *(p+i));//p+i 这⾥就是指针+整数
 }
 return 0;
}

这里就是通过变量 i 生成遍历数组下标的整数0~9,然后在 p+i 中通过指针+整数的方式,依次从前往后的访问数组元素。

那么自然,我们这段代码也可以这样写:

//演示2.1.3

include <stdio.h>

int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 for(i=sz-1; i>=0; i--)
 {
 printf("%d ", *(p+i));
 }
 return 0;
}

2.指针-指针

既然指针里存放的地址本质就是一个数,那么自然可以进行减法运算。

//演示2.2.1

#include <stdio.h>

int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int num = 0;
    int* pa = &arr[0];
    int* pb = &arr[4];
    num = pb - pa;
    printf("num = %d\n",num);
    return 0;
}

单纯看指针中地址的大小的话,一个整型占4个字节,两个地址间应该相差16个字节才对,但结果为什么是4而不是16呢?

前一篇博客中我们讲到,整型指针的类型是int*,*代表这个变量是指针,而int表示这个指针指向对象的类型是int。

可以这样理解,在指针进行减法运算的时候,它们也受到自己类型的影响,*在表示这个变量是指针,int在表示它是整型变量。

在指针减指针的时候,*让他们中存放的地址相减,而int使这个商表示为多少个int类型的数据。也就是说,在上面演示中,地址相减得16字节,而一个整型是4个字节,所以16/4=4,最终结果就会是4。

再看下面这段代码:

//演示2.2.2

#include <stdio.h>

int my_strlen(char *s)
{
 char *p = s;
 while(*p != '\0' )
 p++;
 return p-s;
}

int main()
{
 printf("%d\n", my_strlen("abc"));
 return 0;
}

这里我们首先要知道一个点,就是字符串在传参的时候,传递的是字符串首个字符的地址。所以在my_strlen函数中用字符指针来接收传递过来的参数。

 

不难看出指针s指向字符串首字符,而指针p经过循环后指向了字符串末尾的\0。

经过演示2.1.1的讲解,我们可以知道,这里两个指针p和s中的地址相差了3,而字符类型char的数据占据1个字节,所以3/1=3,最终结果就是3。

3.指针的关系运算

两个指针之间也可以判断大小:

//演示2.3.1

#include <stdio.h>

int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 while(p<arr+sz) //指针的⼤⼩⽐较
 {
 printf("%d ", *p);
 p++;
 }
 return 0;
}

在while循环里,指针p从数组首元素的地址开始,依次自增,知道指向数组最后一个元素。

while循环的判断条件,就运用了指针大小的比较,这个点并不难理解。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值