C 深入指针(1)

目录

一、const

1、const修饰变量

2、const修饰指针

2.1 const int* p(int const* p)

2.2 int* const p

2.3 结论

二、指针运算

1、指针 +- 整数

2、指针 - 指针

3、指针的关系运算

三、指针的使用

1、模拟实现 strlen

2、传值调用和传址调用


一、const

1、const修饰变量

通过上图的报错信息可知,被const修饰的变量无法别修改,那我们试试通过地址修改他

#include<stdio.h>
int main()
{
	const int n = 10;
	int* p = &n;    
	*p = 20;
	printf("%d", n);    //成功输出20!
	return 0;
}

还真可以,这让我想到那些红客哈哈好厉害。

在这里我们明明不想n被改变,结果通过指针给n改了,这是不合理的!那该怎么办呢?


2、const修饰指针

2.1 const int* p(int const* p)

在 * 左边加上const可以看到,*p 无法被修改了

int const* p = &n;    //和 const int* p 等价

2.2 int* const p

那指针内的地址能修改吗

可以看到地址能被修改,指针变量 p 存放的本来是 n 的地址,输出应该是10,结果输出100;说明 p 存放的地址被改成了 m 的地址;地址不想被修改怎么办?

在 * 右边加上const可以看到,p 无法被修改了


2.3 结论

const 如果放在 * 的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。 但是指针变量本身的内容可变。

const 如果放在 * 的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指 向的内容,可以通过指针改变。  

如果都不想被修改,左右都加上const就好啦

const int* const p = &n;

int const* const p = &n


二、指针运算

指针的基本运算有三种,分别是:

  • 指针 +- 整数
  • 指针 - 指针
  • 指针的关系运算

1、指针 +- 整数

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	//依次打印数组内容
	for (int i = 0; i < 10; i++)
	{
		//printf("%d ", arr[i]);
		printf("%d ", *(p + i));	//指针+整数	
	}
	return 0;
}

2、指针 - 指针

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p1 = arr;		//指向数组第一个元素
	int* p2 = arr + 9;	//指向数组最后一个元素
	//输出的是字符串的长度,9
	printf("%zd", p2 - p1);
	return 0;
}

3、指针的关系运算

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p1 = arr;		//指向数组第一个元素
	int* p2 = arr + 9;	//指向数组最后一个元素
	//依次打印数组元素
	while (p1 <= p2)    //关系运算
	{
		printf("%d ", *p1);
		p1++;
	}
	return 0;
}

三、指针的使用

1、模拟实现 strlen

库函数strlen的功能是求字符串长度,统计的是字符串中 \0 之前的字符的个数。

#include<stdio.h>
#include<string.h>	//使用strlen时必须声明的头文件
int main()
{
	char arr[] = "abcd";
	size_t length = strlen(arr);
	printf("%zd", length);	//输出 4
	return 0;
}

通过使用指针来模拟实现 strlen函数:

#include<stdio.h>
int my_strlen(const char* p)
{
	int count = 0;
	while (*p)	//遍历到末尾的 \0 就会终止循环
	{
		count++;
		p++;
	}
	return count;
}
int main()
{
	char arr[] = "abcdef";
	int length = my_strlen(arr);	//模拟strlen
	printf("%d", length);
	return 0;
}

2、传值调用和传址调用

我们通过写一个交换值的函数来告诉这两者的区别

#include<stdio.h>
//传值调用
void swap(int x, int y)	//x = a; y = b
{
	int tmp = x;
	x = y;
	y = tmp;
}
int main()
{
	int a = 1;
	int b = 100;
	printf("交换前:a = %d b = %d\n", a, b);
	swap(a, b);	//想实现交换两个变量的值
	printf("交换后:a = %d b = %d", a, b);
	return 0;
}

运行之后发现 a 和 b 的值根本没有改变,这是为什么,启动调试监测

不清楚为什么是栈区可以看初阶 C语言的变量和算术操作符-CSDN博客

结论:实参传递给形参的时候,形参会单独创建一份临时空间来接收实参,对形参的修改不影响实参。 所以 swap() 失败了。 

所以我们需要传址调用

#include<stdio.h>
//传址调用
void swap(int* x, int* y)	//x = &a; y = &b
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}
int main()
{
	int a = 1;
	int b = 100;
	printf("交换前:a = %d b = %d\n", a, b);
	swap(&a, &b);	//实现交换两个变量的值
	printf("交换后:a = %d b = %d", a, b);
	return 0;
}

这次就成功交换了,这里调用 swap函数 的时候是将变量的地址传递给了函数,这种函数调用方式叫:传址调用

传址调用,可以让函数和主调函数之间建立真正的联系,在函数内部可以修改 main函数 中的变量;所以未来函数中只是需要 main函数 中的变量值来实现计算,就可以采用传值调用。如果函数内部要修改 main函数 中的变量的值,就需要传址调用。


  • 45
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值