C标准库学习
前言
C标准库源码可通过下列两个网站进行查看:The GNU C Library、Welcome to uClibc-ng! - Embedded C library
以下学习记录也是以这两个网站提供的库函数源码进行学习的。
字符串相关
strcpy()函数
头文件:#include <string.h>
函数原型:char *strcpy(char *dest, const char *src);
函数描述:将src指向的字符串拷贝到dest,包括结束符'\0'。字符串不能重叠,并且dest有足够的空间接收拷贝的字符串。
返回值:返回指向dest存放字符串的指针。
函数原型:
char *strcpy(char *dest, const char *src)
{
char *dst = dest;
while ((*dst = *src) != '\0') {
src++;
dst++;
}
return dest;
}
可以看出,函数中并不会检查dest的空间大小,只会拷贝字符串直到遇到src字符串的结束符'\0',因此dest的空间大小需要用户保证。
测试用例一:dest空间大于src指向的字符串个数。
#include <stdio.h>
#include <string.h>
int main(void)
{
char *str_original = "0123456789";
char buf_dest[12] = {0};
char *ret = NULL;
int i = 0;
for (i = 0; i < sizeof(buf_dest); i++)
buf_dest[i] = 1;
printf("dest:0x%x\n", buf_dest);
ret = strcpy(buf_dest, str_original);
printf(" ret:0x%x\n", ret);
for (i = 0; i < sizeof(buf_dest); i++)
printf("%d ", buf_dest[i]);
printf("\n");
return 0;
}
编译,运行结果:
$ ./a.out
dest:0xca8e26c0
ret:0xca8e26c0
48 49 50 51 52 53 54 55 56 57 0 1
可以看出,字符串拷贝的时候会拷贝字符串结束符'\0'。
测试用例二:dest空间小于src指向的字符串个数(错误用法)。
#include <stdio.h>
#include <string.h>
int main(void)
{
char *str_original = "0123456789";
char buf_dest[5] = {0};
char *ret = NULL;
int i = 0;
for (i = 0; i < sizeof(buf_dest); i++)
buf_dest[i] = 1;
printf("dest:0x%x\n", buf_dest);
ret = strcpy(buf_dest, str_original);
printf(" ret:0x%x\n", ret);
for (i = 0; i < sizeof(buf_dest); i++)
printf("%d ", buf_dest[i]);
printf("\n");
return 0;
}
编译,运行:
由于dest没有以'\0'结尾,因此printf打印的信息是错误的,访问的内容已经超过了dest的空间。
测试用例三:内存重叠
参考博客:strcpy函数的实现 - Norcy - 博客园 (cnblogs.com)
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[12] = "hello";
strcpy(str + 1, str); //存在段错误
printf("%s\n", str);
return 0;
}
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[12] = "hello";
strcpy(str, str+1);
printf("%s\n", str); //打印输出ello
return 0;
}
第一种情况:strcpy(str + 1, str),这种情况下dest指向'e',而src第一个字符为'h',当拷贝的时候,'\0'结束符会被覆盖掉,导致一直拷贝,陷入死循环。
第二种情况:strcpy(str, str+1),这种情况下,仅拷贝"ello"。
strncpy()函数
头文件:#include <string.h>
函数原型:char *strncpy(char *dest, const char *src, size_t n);
函数描述:功能和strcpy函数类似,但仅拷贝src的n字节给dest。另外如果n字节中没有结束符'\0',那么拷贝完后,dest中是不会有结束符的,这个需要注意。如果src的长度小于n字节,将会在拷贝src字符串之后继续拷贝结束符给dest,直到满足n字节。
函数原型:
char *strncpy (char *s1, const char *s2, size_t n)
{
reg_char c;
char *s = s1;
--s1;
if (n >= 4)
{
size_t n4 = n >> 2;
for ( ; ; )
{
c = *s2++;
*++s1 = c;
if (c == '\0')
break;
c = *s2++;
*++s1 = c;
if (c == '\0')
break;
c = *s2++;
*++s1 = c;
if (c == '\0')
break;
c = *s2++;
*++s1 = c;
if (c == '\0')
break;
if (--n4 == 0)
goto last_chars;
}
n = n - (s1 - s) - 1;
if (n == 0)
return s;
goto zero_fill;
}
last_chars:
n &= 3;
if (n == 0)
return s;
do
{
c = *s2++;
*++s1 = c;
if (--n == 0)
return s;
} while (c != '\0');
zero_fill:
do
*++s1 = '\0';
while (--n > 0);
return s;
}
测试用例一:src字符串长度大于n,且前n个字符中存在结束符,则只会拷贝到第一个结束符时就结束拷贝。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str_original[] = {'a', '\0', 'b', '\0', 'c', 'd', 'e', '\0'};
char str_dest[8] = {0};
int i = 0;
strncpy(str_dest, str_original, 8);
for (i = 0; i < 12; i++)
printf("%d ", str_dest[i]);
printf("\n");
return 0;
}
编译,运行:
$ ./a.out
97 0 0 0 0 0 0 0
测试用例二:src字符串长度大于n,且前n个字符中不存在结束符,则会拷贝n个字符。处理这种情况,一般需要自己去在dest末尾添加一个结束符。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str_original[] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
char str_dest[5] = {0};
int i = 0;
strncpy(str_dest, str_original, 5);
for (i = 0; i < 5; i++)
printf("%d ", str_dest[i]);
printf("\n");
return 0;
}
编译,运行:
$ ./a.out
97 98 99 100 101
测试用例三:src字符串长度小于n,将会在拷贝src字符串之后继续拷贝结束符给dest,直到满足n字节。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str_original[] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
char str_dest[12] = {0};
int i = 0;
for (i = 0; i < 12; i++)
str_dest[i] = 1;
strncpy(str_dest, str_original, 12);
for (i = 0; i < 12; i++)
printf("%d ", str_dest[i]);
printf("\n");
return 0;
}
编译,运行:
$ ./a.out
97 98 99 100 101 102 0 0 0 0 0 0
C标准库学习的更多相关文章
- C++STL标准库学习笔记(三)multiset
C++STL标准库学习笔记(三)multiset STL中的平衡二叉树数据结构 前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标 ...
- python标准库学习-SimpleHTTPServer
这是一个专题 记录学习python标准库的笔记及心得 简单http服务 SimpleHTTPServer 使用 python -m SimpleHTTPServer 默认启动8000端口 源码: &q ...
- C++STL标准库学习笔记(一)sort
前言: 近来在学习STL标准库,做一份笔记并整理好,方便自己梳理知识.以后查找,也方便他人学习,两全其美,快哉快哉! 这里我会以中国大学慕课上北京大学郭炜老师的<程序设计与算法(一)C语言程序设 ...
- Go标准库学习之OS常用函数
1.OS基础操作 //获取主机名 os.Hostname() //获取当前目录 os.Getwd() //获取用户ID os.Getuid() //获取有效用户ID os.Geteuid() //获取 ...
- C++STL标准库学习笔记(五)set
前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标记了出来,这一篇后面主要都是我的记录了,为了防止大片蓝色字体出现,后面就不改蓝色 ...
- C++STL标准库学习笔记(二)二分查找
二.STL中的二分查找算法 1.binary_search 2.lower_bound 3.upper_bound 记得#include<algorithm>! 前言: 在这个笔记中,我把 ...
- Python3 标准库学习
python3.5.6 官方文档 https://docs.python.org/3.5/library/index.html 1.介绍 2.内置函数 3.内置常量 3.1常数添加的 site模块 ...
- Python标准库学习之zipfile模块
ZipFile模块里有两个非常重要的class, 分别是 ZipFile和ZipInfo. ZipFile是主要的类,用来创建和读取zip文件,而ZipInfo是存储的zip文件的每个文件的信息的. ...
- python标准库学习-ftplib
源码: """An FTP client class and some helper functions. Based on RFC 959: File Transfer ...
随机推荐
- OpenCV读写图像文件解析
OpenCV读写图像文件解析 imdecode 从内存中的缓冲区读取图像. C++:Mat imdecode(InputArray buf, int flags) C++:Mat imdecode(I ...
- UF_TRNS 变换相关
Open C uf5940uf5941uf5942 矩阵乘积变换uf5943 平移变换uf5944 缩放变换uf5945 旋转变换uf5946 镜像变换uf5947 实现变换,根据变换矩阵 ...
- 摆脱鼠标之Dos学习
2015/12/24 for循环 1,创建文件 http://blog.csdn.net/wangxingbao4227/article/details/17009447 关于for循环的总结,很详细 ...
- 【Java】Debug断点调试常用技巧
Debug操作技巧 Show Execution Point 将光标回到当前断点停顿的地方 Step Over 执行当前行代码,并将运行进度跳转到下一行. Step Into 进入到当前代码行的方法内 ...
- NOIP模拟测试29「爬山·学数数·七十和十七」
爬山题解不想写了 学数数 离散化然后找到以每一个值为最大值的连续子段有多少个,然后开个桶维护 那么怎么找以每一个值为最大值的连续子段个数 方法1(我的极笨的方法) 考试时我的丑陋思路, 定义极左值为左 ...
- 带你掌握4种Python 排序算法
摘要:在编程里,排序是一个重要算法,它可以帮助我们更快.更容易地定位数据.在这篇文章中,我们将使用排序算法分类器对我们的数组进行排序,了解它们是如何工作的. 本文分享自华为云社区<Python ...
- Hive和Spark分区策略
1.概述 离线数据处理生态系统包含许多关键任务,最大限度的提高数据管道基础设施的稳定性和效率是至关重要的.这边博客将分享Hive和Spark分区的各种策略,以最大限度的提高数据工程生态系统的稳定性和效 ...
- ES6学习笔记之字符串新增方法
1.字符串的子串识别 传统上,Javascript 只有indexof 方法,用来确定一个字符串是否包含在另一个字符串中.如: //indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的 ...
- 38、mysql数据库(pymysql及事务)
38.1.python之pymysql模块: 1.说明: pymsql是Python中操作MySQL的模块,其使用方法和py2的MySQLdb几乎相同. 2.模块安装: pip install pym ...
- CentOS-配置YUM源加速(阿里云、Nexus3)
备份本地源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 配置CentOS6(aliyun ...