c一些小细节

模拟strcpy

一份代码不仅注重结果,优秀的代码一定要注意以下方面:

  • 使用assert
  • 常用const
  • 养成好的编码风格
  • 添加必要的注释
  • 避免编码的陷阱

越界访问

先来看一段越界代码:

 这段代码陷入了死循环,但为什么呢,我们调试观察一下。

可以发现在我们第12次循环赋值后,i的值也变成了0,好像是跟着arr[12]一起改变的,我们打印一下它们的地址来验证我们的猜测。

 

它们的地址竟然是一样的!要想解释这个现象,就要考虑栈空间的存储结构了。栈区中储存数据时先使用高地址后使用低地址。由于我们先创建的i变量再创建的数组,就可能导致越界访问时修改i的值。

 

注:中间相隔多少个元素取决于编译器。

模拟strcpy

先来看看库函数中的strcpy函数是怎样实现的:  

 大家看看这样的代码有什么问题:

void my_strcpy(char* str, char* scr)
{
	while (*str++ = *scr++)
	{
		;
	}
}

函数接收了两个char*类型的指针变量,如果为空指针,那程序就会出错,所以我们可以添加assert来进行断言。

#include<aseert.h>
	assert(str != NULL);//断言
	assert(scr != NULL);//断言

	assert(str);//断言
	assert(scr);//断言

	assert(str && scr);//断言

其次,被拷贝的变量可以在前面加上const使其无法修改指向的值,如果不小心将赋值写反了就能被编译器检测出,我们代码的健壮性也会大大提高。

*src = *str;//ERR

此外,对比库函数具有返回值char*,使其可以作为参数被接收,我们可以这样修改 

char* my_strcpy(char* str, const char* scr)
{
	char* ret = str;
	assert(dest && src);

	while (*str++ = *scr++)
	{
		;
	}
	return ret;
}

注意返回值必须是函数首地址,所以需要先储存目标变量的地址。 

const用法

const修饰变量使其转换为具有常属性的常变量,本质上是变量,只是具有了常属性。通过定义数组可以发现[ ]内使用它会被不支持变长数组的编译器认为变量。

const int a = 0;

const修饰的指针 

被它修饰的指针无法改变指向对象的值,但是如果你想改变该指针指向的地址,发现是可以的。

int a = 0;
int b = 0;
//const int a = 0;
const int *p = &a;
\\错误写法*p = 10;
p = &b;

下面两条语句的意思是相同的:

const int *a;
int const *a;

常量指针

在*后面加上const,被它修饰的指针自身无法改变、赋值,但可以通过解引用操作指向的空间

int a = 0;
int *const p = &a;
*p = 10;

指向常量的常指针

指针常量则是二者结合,既不能通过它改变地址,也不能通过它改变地址所储存的值。 

int a = 0;
const int *const p = &a;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小C您好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值