我们新年好呀,春节这段时间太忙了,一向没有写文章,这两天才想起来应该搞搞学习了,就把年前写的atm项目中遇到的一些问题整理出来,供需求的人参阅学习,也供自己回顾温习。

C言语编程问题剖析,以及过错解决方法

1. void*指针类型

一开始学习C言语时,对void*这个类型没有过多的了解与关注,只知道是“没有类型的指针”,没有用过,在写atm这个项目的时分,才真实去了解它。

C言语编程问题剖析,以及过错解决方法

void*类型是一个指向未知类型的指针,不能直接用于拜访指向的数据。

其实,各种类型之间没有实质的差异,void*也相同,只是解释内存中的数据方式不同,int*指向的内存中存储着数字,char*指向的内存中存储着字符串。假如需求转化为特定的数据类型,需求根据详细的数据类型进行强制类型转化,才能正确的拜访和操作数据。但需求留意的是,在进行void*向特定类型的数据转化时,需求保证原始的void*指针指向的内存确实包含了有用的转化指针数据,不然可能会导致未界说行行为。

  • 比方,void*类型转化为char*类型,保证void*转化时指向的内存中存储的便是char类型数据即可。
  • 特定类型的数据也能够转化为void*类型。因为void*是一种通用的指针类型,能够承受任何类型的指针。比方,char*类型转化为void*类型,只需求强制转化,刺进类型转化为void*类型不会丢失任何信息,只需求保证在转化之前正确地分配内存。

C言语编程问题剖析,以及过错解决方法

在很多通用的函数接口中,给的都是参数类型都是void*。

比方:void* memcpy(void* dest,const void* src,size_t n);

其间,dest是指向目标内存地址的指针,src是指向源内存地址的指针,n是要被仿制的字节数。这个函数返回一个指向目标内存地址的指针。运用memcpy函数能够便利的将一段内存中的数据仿制到另一段内存中,而不需求手动逐个字节地仿制。

这样设计的目的是,因为你不知道用户的数据类型是什么,但是你有必要能够,处理用户的各种数据类型,所以会运用void*,void*能包容的承受各种类型的指针。假如你希望接口能够承受任何类型的参数,你能够运用void*类型,但在详细运用的时分,你有必要转化为详细的指针类型。

C言语编程问题剖析,以及过错解决方法

在运用void*需求特别留意的是,你有必要清楚原始传入的是什么类型,然后转化成对应的类型。

void*很强大,但是必定要在适宜的时分运用;

2. 读取/写入方位产生拜访冲突

遇到 C/C++程序运行时提示“读取/写入方位产生拜访冲突”。

产生原因:一般都是因为产生反常处的代码中,涉及到数据的读取或写入,而且拜访数据时运用的是指针,而该指针并未得到适宜的初始化,导致其所指向内存为NULL。

解决方法:

  • 写入冲突:初始化变量;
  • 读取冲突:输出类型写正确;

3. while循环中有Switch,怎么跳出while循环

3.1. while循环用boolean变量操控

switch中的break只能停止switch循环,无法停止while循环,假如将break改为return,虽然能停止循环,但是也会用力过猛,整个方法都会停止。

怎么做到准确的停止掉当时while循环,我们能够在外面界说一个boolean变量flag来操控while循环,通过改变flag的值来操控while循环。

如下是atm系统中“修正用户信息”函数的部分代码:

//修正用户信息 
void updateInfo(){
	int i=0;
	int flag = 1;
	Customer *user = (Customer*)getData(hashmap,custCurrent->accountCard);
	while(flag){
		scanf("%d",&i);
		switch(i){
		case 1:printf("请输入账户名称:n");scanf("%s", &user->accountName);break;
		case 2:printf("请输入电话号码:n");scanf("%s", &user->mobile);break;
		case 3:printf("请输入要修正的密码:n");scanf("%s", &user->password);break;
		case 0:flag = 0;break;
		default:printf("输入有误,请输入对应的值");
		}
    }
	printf("修正用户信息成功! ");
	return;
}

在修正用户信息函数中,一开始我并没有运用flag变量,导致循环总是出现提早停止或堕入死循环的问题,后面奇妙的运用了一个flag变量去操控循环的停止就能够完美的实现啦。

4. static关键字

4.1. 润饰部分变量

运用static润饰的部分变量不会在函数重新进入时再次赋初值,不会在函数完毕时而释放(存储在大局区),也不会在循环中多次赋初值。这种变量的效果域为部分效果域,当界说它的函数完毕时,其效果域随之完毕。运用static润饰的部分变量存储于进程的大局数据区,即使函数返回,它的值也会坚持不变。

4.2. 润饰大局变量

运用static润饰的大局变量仅对当时文件可见,其他文件不行拜访,其他文件能够界说与其同名的变量,两者相互不影响。在界说不需求与其他文件同享大局变量时,加上static关键字能够有用地下降程序模块化之间的耦合,避免不同文件同名变量的冲突,且不会误运用。

4.3. 润饰函数

运用static润饰的函数只能在本文件中调用,不能在其他文件中调用。这种函数没有this指针,它无法拜访属于类对象的非静态数据成员,也无法拜访非静态成员函数,它只能调用其余的静态成员函数。出现在类体外的函数界说不能指定关键字static

C言语编程问题剖析,以及过错解决方法