之前对于一些标准库函数都是拿来即用,没有考虑过这个函数的优缺点及具体的实现形式,在实习期间,一个标准库函数都是被二次封装了的,还是很有趣的。比如对于malloc函数,内部的形式是void *malloc_s(int ENUM_TYPE, int size),多了一个参数ENUM_TYPE,比如对于我们TM就是MALLOC_TMBUFFER,其原因是因为这样写方便对堆区内存进行统计,防止有的小组malloc空间过大,这样可以及时定位。
本博客将参考Linux常用C函数手册进行标准库函数的一一实现(长期更新)。
1、memcpy实现
/* 标准库中的memcpy是要确保地址不重合
* 附加说明指针src和dest所指的内存区域不可重叠
*/
/* 实现一:
* 不考虑内存重叠 */
void *memcpy_s(void *des, void *src, int len)
{
if (des == NULL || src == NULL) {
return NULL;
}
void *ret = des;
while (len--)
{
*(char *)des = *(char *)src;
(char *)des++;
(char *)src++;
}
return ret;
}
2、memmove实现
/* 实现二:
/* 考虑内存重叠的情况,此时类似于memmove
* #include<string.h>
定义函数
void *memmove(void *dest,const void *src,size_t n);
函数说明 : memmove()与memcpy()一样都是用来拷贝src所指的内存内容前n个字节到dest所指的地址上。
不同的是,当src和dest所指的内存区域重叠时,memmove()仍然可以正确的处理,不过执行效率上会比使用memcpy()略慢些。
返回值 : 返回指向dest的指针。
附加说明 :指针src和dest所指的内存区域可以重叠。
*/
void *memmove_s(void *des, const void *src, int len)
{
void *ret = des;
if (des == NULL || src == NULL) {
return NULL;
}
if (src < des) {/* 低地址往高地址复制 : 高 -> 高*/
while (len--) {
*(char *)(des+len) = *(char *)(src+len);
}
} else {
while (len--)
{
*(char *)des = *(char *)src;
des++;
src++;
}
}
return ret;
}
3、strcmp实现
/* strcmp_s实现 */
int strcmp_s(char *str1, char *str2)
{
int ret = 0;
if (str1 == NULL || str2 == NULL) {
return -1;
}
while ((*(str1) != ' ') && (*(str2) != ' ') && (*(str1) == *(str2))) {
str1++;
str2++;
printf("*str1 = %c\n", *(str1));
}
ret = *(str1) - *(str2);
return ret;
}
4、strcpy实现
/* strcpy_s 实现 */
char *strcpy_s(char *des, char *src)
{
char *ret = des;
if ((des == NULL) || (src == NULL)) {
return NULL;
}
while (*(src) != '\0')
{
*(des) = *(src);
des++;
src++;
}
*(src) = '\0';
return ret;
}
5、strlen实现
sizeof和strlen的区别:
strlen( )计算字符串的长度,以'\0'为字符串结束标志。
sizeof( )是分配的数组实际所占的内存空间大小,不受里面存储内容。
sizeof( )是运算符,由于在编译时计算,因此sizeof( )不能用来返回动态分配的内存空间的大小。实际上,用sizeof( )来返回类型以及静态分配的对象、结构或数组的空间,返回值跟这些里面所存储的内容没有关系。
具体而言,当参数分别如下时,sizeof返回的值含义如下:
数组 -- 编译时分配的数组空间大小
指针 -- 存储该指针所用的空间大小
类型 -- 该类型所占的空间的大小
对象 -- 对象的实际占用空间大小
函数 -- 函数返回类型所占空间的大小
strlen()是函数,可以计算字符串的长度,直到遇到结束符NULL才结束,返回的长度大小不包含NULL。
ubuntu@VM-0-4-ubuntu:~/share/codeForTest$ ./10-08 sizeof(str1) = 8 strlen(str1) = 7 sizeof(str2) = 20 strlen(str2) = 7 ubuntu@VM-0-4-ubuntu:~/share/codeForTest$ cat 10-08.c #include "stdio.h" int main() { char *str1 = "absdefg"; char str2[20] = "abcdefg"; printf("sizeof(str1) = %d\n", sizeof(str1)); printf("strlen(str1) = %d\n", strlen(str1)); printf("sizeof(str2) = %d\n", sizeof(str2)); printf("strlen(str2) = %d\n", strlen(str2)); return 0; }
unsigned int strlen_s(char *str)
{
if (str == NULL) {
return 0;
}
unsigned int len = 0;
while (*str != '\0') {
len++;
str++;
}
return len;
}
6、atoi的实现
int atoi_s(char *src)
{
if (src == NULL) {
return 0;
}
while (*src == ' ') {
src++;
}
int signalFlag = 1;
int ans = 0;
if (*src == '-') {
signalFlag = -1;
}
if (*src == '-' || *src == '+') {
src++;
}
while (*src > '0' && *src <= '9')
{
ans = ans * 10 + *src - '0';
src++;
}
ans *= signalFlag;
return ans;
}