C语言初阶———指针(2)

1.const 修饰指针

1.1const修饰变量

变量是可以修改的,如果把一个变量的地址交给一个指针变量,通过指针变量的也可以修改这个变量,但是如果我们希望加上一些限制,不能被修改,,怎么做呢?这就是const的作用。

#include<stdio.h>

int main(void)
{
	const int a = 10;	//const前加,a具有了常属性(不能被修改了)
	//a是不是常量呢?虽然a是不能被修改的,但是本质上还是变量,也称为常变量
	//a = 20;a会报错

	int arr[a];//在C++中没有报错,const修饰的变量就是常量,在C语言中会报错
	printf("%d\n", a);

	return 0;
}

 1.2 const修饰指针变量

1.2.1 const修饰指针变量的时候,放在*的右边
#include<stdio.h>

int main(void)
{
	int a = 10;
	int b = 20;
	int* const p = &a;	//const修饰指针变量的时候,放在*的右边,

	//p = &b;//这里会报错
	*p = 100;//没有报错
	printf("%d\n", a);	//100
	//const限制的是指针变量本身,指针变量不能再指向其他变量了
	//但是可以通过指针变量,修改指针变量指向的内容

	return 0;
}
1.2.2 const修饰指针变量的时候,放在*的左边
#include<stdio.h>

int main(void)
{
	int a = 10;
	int b = 20;
	int const* p = &a;	//const修饰指针变量时,放在*的左边,
	p = &b;//没有报错
	//*p = 100;//会报错
	printf("%d\n", a);//10
	//限制的是:指针指向的内容,不能通过指针来修改指向的内容
	//但是可以修改指针变量本身的值(修改的指针变量的指向)
	return 0;
}

总的来说,凡是const后面的内容均不可修改。如果*的右边跟左边都有const修饰,

int const * const p; ,那么*p=0p=* n 都是会报错的,const在两边修饰任何一种都不可修改!

2.assert断言

assert.h头文件定义了宏assert(),用于在运行时确保程序符合指定条件,,如果不符合,就报错终止运行,这个宏被称为“断言”。

assert(p != NULL);

assert()宏接受一个表达式作为参数,如果该表达式为真(返回值不为0),assert()不会产生任何作用,程序继续运行,如果一个表达式为假(返回值为0),assert()就会报错。

作用:不仅可以自动标识文件和出问题的行号,还有一种无需更改代码就能开启或关闭assert()的机制,如果已经确认程序没有任何问题,不需要再做断言,就在#include<assert.h>语句的前面,定义一个宏NDEBUG

然后重新编译程序,编译器会禁用文件中所有的assert()语句,如果程序又出现问题,可以移除这条#define NDEBUG 指令,(或者把它注释掉),再次编译,这样就重新启用了assert()语句。

assert()语句的缺点是,因为引入了额外的检查,增加了程序运行的时间。

 3.指针的使用和传址调用

3.1 strlen的模拟实现

参数 str 接收一个字符串的起始地址,然后开始统计字符串中\0之前的字符个数,最终返回长度。
止。如果要模拟实现只要从起始地址开始向后逐个字符的遍历,只要不是\字符,计数器就+1,这样直到\0就停。

 

 这里为什么会这样,因为在主函数my_strlen后面的括号里面写了NULL(被挡住了),这个是有问题的,没有直接报错是因为加了宏#define NDEBUG,,如果没写,是直接在assert(str != NULL);这里断言出错,但是如果里面传的实参是arr,程序会正常运行,打印出数组长度6。

3.2 传值调用和传址调用

 

写一个函数,交换两个整型变量的值。

//写一个函数,交换两个整数的内容

#include<stdio.h>

void swap2(int *pa, int*pb)
{
	int tmp = 0;
	tmp = *pa;	//tmp=a
	*pa = *pb;	//a=b
	*pb = tmp;	//b=tmp
}
int main(void)
{
	int a = 10;
	int b = 20;
	printf("交换前:a=%d b=%d\n", a, b);	//10  20
	swap2(&a, &b);//传址调用
	printf("交换后:a=%d b=%d\n", a, b);	//20  10
	return 0;
}
//当实参传递给形参的时候,形参是实参的一份临时拷贝
//对形参的修改不会影响实参的

4.数组名的理解

 sizeof (数组名), sizeof 中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节.

&数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)

那么这三个地址表示是完全一样的吗?给每一个数组后面加1来看。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值