(改进版)宏实现C语言任意类型的安全数组
2022-10-31 本文已影响0人
黑熊小李
前述
在我的上一篇文章《利用宏实现C语言任意类型的安全数组》中留下的代码,经过我反复品味,发现还有一些不足,例如:
- Create_Array 宏的模块化程度不高,有比较重的散装感,也就是耦合度高。
- Destroy_Array 宏没有对于情况的仔细分析处理分支,不安全。
- 原Array 结构体不应该别称为Array ,它更像是一种通用的安全结构。
- 命名上的不规范,不能达到显而易见的效果。
改进
针对以上不足,做出如下改进:
- 规范了命名,使得通过名字就能确定所属关系和类型。
- 抽象出一个通用的 Box 结构,避免歧义。
- 使用单个函数封装了创建 Box 结构的功能,模块化成度更高。
- 简化宏的结构,为宏添加必要的处理分支。
- 添加了必要的注释,方便阅读。
代码:
#include<stdio.h>
#include<stdlib.h>
// 可以通用的 内容+大小 结构
typedef struct {
size_t size;
void *private;
}Box;
// 创建一个Box对象,并为私有成员开辟需要的空间
Box *Box_new(size_t size, size_t typesize) {
Box *out = calloc(1, sizeof(Box));
if (out != NULL) {
out->private = calloc(size,typesize);
if (out->private != NULL) {
out->size = size;
return out;
}
else {
free(out);
out=NULL;
}
}
return out;
}
// 释放分配的空间
void Box_delete(Box *opj){
if(opj->private != NULL) {
free(opj->private);
}
free(opj);
}
/** if 分配成功
* 生成两个指针
* 一个指向结构
* 一个具象化的类型指针,指向结构中的私有成员
* else 两个堆内存,任意一个分配失败
* 生成两个空指针
*/
#define Box_get_as_type(name, type) \
type *name##_ptr = NULL; \
if(name != NULL) { name##_ptr = name->private; } \
#define Box_create(name, type, length) \
Box *name = Box_new(length, sizeof(type)); \
/** if 数组指针不为空
* 分配的内存,遵循由内部向外部逐步释放原则
* 优先把 private 的别名指针置空
* 清理结构体内部动态内存
* 清理结构体动态内存
*/
#define Box_destory(name) \
if(name) { \
Box_delete(name); \
name=NULL; \
}
void fn(int *opj, size_t size){
for(int i=0; i < size; i++) {
opj[i]=i*2;
if(i < size-1) printf("%d->",opj[i]);
else printf("%d\n总数:%zu 个\n",opj[i],size);
}
}
int main(){
Box_create(an, int, 10)
Box_get_as_type(an, int)
if(an) fn(an_ptr, an->size);
Box_destory(an)
}
结果:
Safe_Power疑问:
在之前印象里,free函数只是释放了这个指针指向的地址,指针值应该不变,但是在这里,结构体中 private 指针释放后,值发生变化,而结构体指针的值却不变的?!都是calloc分配的,怎么会有诡异的现象?虽然不耽误啥,但就是想不通。
注意
文章为本人在简书平台原创,盗用必究!