c语言 实现切片数组

本文介绍了如何在C语言中借鉴Go语言的slice特性,实现了一个动态数组接口,简化了创建、销毁切片以及添加元素的操作,提高代码可读性和使用便利性。
摘要由CSDN通过智能技术生成

文章目录

前言

由于c语言没有集合类的标准库,需要用时只能自己实现,由于c语言没有泛型,使得实现的集合类接口通常比较另类,很多时候都需要二级指针作为参数,且不支持字面量作为参数,使用时心智负担较重。本文参考go语言的slice,找到了一种非常简化的动态数组接口,可以极大的方便使用。


一、接口定义

1、创建切片

指定元素类型,以及容量即可以创建切片,返回是一个数组

/// <summary>
/// 创建切片
/// </summary>
/// <param name="t">元素类型</param>
/// <param name="len">切片长度</param>
/// <param name="cap">[可选]切片容量,容量必须大于等于长度</param>
/// <returns>切片数组</returns>
#define make(...)

2、销毁切片

与go语言不同,c语言需要管理内存。用完后的切片需要销毁。

/// <summary>
/// 销毁切片
/// </summary>
/// <param name="a">切片数组</param>
#define unmake(a)

3、添加元素

可以添加元素也可以添加数组,数组长度会自动增长。

/// <summary>
/// 添加元素、数组
/// </summary>
/// <param name="a">切片数组</param>
/// <param name="e">元素、数组</param>
/// <param name="l">[可选]数组长度,e为数组时需要此项</param>
#define append(...)

4、切片长度

获取切片长度

/// <summary>
/// 切片长度
/// </summary>
/// <param name="a">切片数组</param>
/// <returns>切片长度</returns>
#define len(a)

5、切片容量

获取切片容量

/// <summary>
/// 切片容量
/// </summary>
/// <param name="a">切片数组</param>
/// <returns> 切片容量</returns>
#define cap(a)


二、完整代码

slice.h

#ifndef SLICE\_H
#define SLICE\_H
#include<stddef.h>
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\* @Project: Slice
\* @Decription: 切片
\* 相当于动态数组,用法与go语言的slice类似
\* @Verision: v1.0.0
\* @Author: Xin Nie
\* @Create: 2024/03/25 01:02:00
\* @LastUpdate: 2024/03/25 01:02:00
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\* Copyright @ 2024. All rights reserved.
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/// <summary>
/// 创建切片
/// </summary>
/// <param name="t">元素类型</param>
/// <param name="len">切片长度</param>
/// <param name="cap">[可选]切片容量,容量必须大于等于长度</param>
/// <returns>切片数组</returns>
#define make(...)\_MAKE\_RELOAD\_CALL(\_\_VA\_ARGS\_\_)
/// <summary>
/// 销毁切片
/// </summary>
/// <param name="a">切片数组</param>
#define unmake(a)\_slice\_umake(a);a=0
/// <summary>
/// 添加元素、数组
/// </summary>
/// <param name="a">切片数组</param>
/// <param name="e">元素、[可选]数组</param>
/// <param name="l">[可选]数组长度,e为数组时需要此项</param>
#define append(...)\_APPEND\_RELOAD\_CALL(\_\_VA\_ARGS\_\_)
/// <summary>
/// 切片长度
/// </summary>
/// <param name="a">切片数组</param>
/// <returns>切片长度</returns>
#define len(a) \_slice\_len( a)
/// <summary>
/// 切片容量
/// </summary>
/// <param name="a">切片数组</param>
/// <returns>切片容量</returns>
#define cap(a) \_slice\_cap( a)
///私有方法
#define \_ACF\_ARG\_T(t) t 
#define \_ACF\_ARG\_N(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,N,...) N
#define \_ACF\_ARG\_N\_HELPER(...) \_ACF\_ARG\_T(\_ACF\_ARG\_N(\_\_VA\_ARGS\_\_)) 
#define \_ACF\_ALIGN(x, a) (((x)+(a)-1)&~((a)-1))
#define \_APPEND\_RELOAD\_CALL(...) \_ACF\_ARG\_N\_HELPER(\_\_VA\_ARGS\_\_,16,15,14,13,12,11,10,9,8,7,6,5,4,\_APPEND\_ARRAY(\_\_VA\_ARGS\_\_),\_APPEND(\_\_VA\_ARGS\_\_),1 ,0) 
#define \_MAKE\_RELOAD\_CALL(...) \_ACF\_ARG\_N\_HELPER(\_\_VA\_ARGS\_\_,16,15,14,13,12,11,10,9,8,7,6,5,4,\_MAKE3(\_\_VA\_ARGS\_\_),\_MAKE2(\_\_VA\_ARGS\_\_),1 ,0) 
#define \_APPEND(a,e)a=\_slice\_append(a,0,sizeof(\*a));a[len(a)-1] = e
#define \_APPEND\_ARRAY(a,e,l)\_slice\_appendArray(a,sizeof(\*e),e,l)
#define \_MAKE2(t,l)\_slice\_make(sizeof(t),l,\_ACF\_ALIGN(l,4))
#define \_MAKE3(t,l,c)\_slice\_make(sizeof(t),l,c)
void\* \_slice\_make(size\_t elementSize, size\_t sliceSize,size\_t sliceCap);
void\* \_slice\_append(void\* array, void\* element, size\_t elementSize);
void\* \_slice\_appendArray(void\* array, size\_t elementSize, void\* array2, size\_t array2Size);
size\_t \_slice\_len(void\* array);
size\_t \_slice\_cap(void\* array);
void \_slice\_umake(void\* array);
#endif

slice.c

#include "slice.h"
#include<stdlib.h>
typedef struct Slice {
	int length;
	int capacity;
	int elementSize;
}Slice;

void\* \_slice\_make(size\_t elementSize, size\_t sliceSize, size\_t sliceCap) {
	Slice\* slice = malloc(elementSize \* sliceCap + sizeof(Slice));
	if (slice){
		slice->capacity = sliceCap;
		slice->elementSize = elementSize;
		slice->length = sliceSize;
		return slice + 1;
	}
	return NULL;
}

void\* \_slice\_append(void\* array, void\* element, size\_t elementSize) {
	Slice\* slice = (array ? (Slice\*)array : (Slice\*)\_slice\_make(elementSize, 0, 4)) - 1;
	if (slice->capacity == slice->length) {
		slice->capacity = slice->capacity == 0 ? 4 : \_ACF\_ALIGN(slice->capacity \* 2, 4);
		if ((slice = realloc(slice, slice->capacity \* slice->elementSize + sizeof(Slice))) == NULL)return NULL;
	}
	if (element)memcpy((char\*)(slice + 1) + slice->elementSize \* slice->length, element, slice->elementSize);
	slice->length++;
	return  slice + 1;
}

void\* \_slice\_appendArray(void\* array, size\_t elementSize, void\* array2, size\_t array2Size) {
	Slice\* slice = (array ? (Slice\*)array : (Slice\*)\_slice\_make(elementSize, 0,\_ACF\_ALIGN(array2Size,4))) - 1;
	if (slice->capacity < slice->length + array2Size) {
		slice->capacity = \_ACF\_ALIGN(slice->length + array2Size, 4);
		if ((slice = realloc(slice, slice->capacity \* slice->elementSize + sizeof(Slice))) == NULL)return NULL;
	}
	memcpy((char\*)(slice + 1) + slice->elementSize \* slice->length, array2, slice->elementSize \* array2Size);
	slice->length += array2Size;
	return  slice + 1;
}

size\_t \_slice\_len(void\* array) {
	if (!array)return 0;
	Slice\* slice = (Slice\*)array - 1;
	return slice->length;
}

size\_t \_slice\_cap(void\* array) {
	if (!array)return 0;
	Slice\* slice = (Slice\*)array - 1;
 **自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/95536c41f7976f7060d7250f61987a43.png)

![img](https://img-blog.csdnimg.cn/img_convert/f384a181a82bbdfd6157b7eb50b38fd3.png)

![img](https://img-blog.csdnimg.cn/img_convert/cababb77851a8116693aec512bb6869e.png)

![img](https://img-blog.csdnimg.cn/img_convert/97de5072b5aaff9f34c54ad98f50dd3e.png)

![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)

![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)**

2fe4e9.png)

![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)**

![](https://img-blog.csdnimg.cn/img_convert/5039819051a0c6ee918af1c7d3f4a067.jpeg)
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值