走进C标准库(7)——"string.h"中函数的实现memcmp,memcpy,memmove,memset
我的memcmp:
int memcmp(void *buf1, void *buf2, unsigned int count){
int reval;
while(count && !(reval = (*(unsigned char *)buf1) - (*(unsigned char *)buf2)))
{
buf1 = (unsigned char *)buf1 + ;
buf2 = (unsigned char *)buf2 + ;
--count;
}
return reval;
}
MS VC:
int __cdecl memcmp (
const void * buf1,
const void * buf2,
size_t count
)
{
if (!count)
return(); while ( --count && *(char *)buf1 == *(char *)buf2 ) {
buf1 = (char *)buf1 + ;
buf2 = (char *)buf2 + ;
} return( *((unsigned char *)buf1) - *((unsigned char *)buf2) );
}
应该使用const void *buf为宜,不改变该块内存的内容,最终使用unsigned char *进行运算,保证运算结果的符号正确。
我的memcpy:
void *memcpy(void *dest, const void *src, unsigned int count){
void *reval = dest;
while(count--){
(*(unsigned char *)dest++) = (*(unsigned char *)src++);
}
return reval;
}
MSVC:
void * __cdecl memcpy (
void * dst,
const void * src,
size_t count
)
{
void * ret = dst; #if defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC)
{
extern void RtlMoveMemory( void *, const void *, size_t count ); RtlMoveMemory( dst, src, count );
}
#else /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */
/*
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + ;
src = (char *)src + ;
}
#endif /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */ return(ret);
}
我的memmove:
void *memmove(void *dest, const void *src, unsigned int count){
void *reval = dest;
int overlap = ((unsigned char *)src < (unsigned char *)dest && ((unsigned char *)src + count) > dest);
while(count--){
if(overlap)//src is in front of dest and overlap. copy direction is from endIndex to beginIndex
(*((unsigned char *)dest + count)) = (*((unsigned char *)src + count));
else
(*(unsigned char *)dest++) = (*(unsigned char *)src++);
}
return reval;
}
MSVC:
void * __cdecl memmove (
void * dst,
const void * src,
size_t count
)
{
void * ret = dst; #if defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC)
{
extern void RtlMoveMemory( void *, const void *, size_t count ); RtlMoveMemory( dst, src, count );
}
#else /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */
if (dst <= src || (char *)dst >= ((char *)src + count)) {
/*
* Non-Overlapping Buffers
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + ;
src = (char *)src + ;
}
}
else {
/*
* Overlapping Buffers
* copy from higher addresses to lower addresses
*/
dst = (char *)dst + count - ;
src = (char *)src + count - ; while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst - ;
src = (char *)src - ;
}
}
#endif /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */ return(ret);
}
关于memcpy和memmove的区别,memcpy不考虑内存区域重叠的情况而memmove保证内存区域重叠也能正常复制成功。
有时候我们的memcpy也可能在内存重叠的情况下正常使用,这取决于它的实现,不具有普遍性,C语言标准中未对其有这种要求。
参考资料:
《关于memcpy和memmove两函数的区别》
http://blog.csdn.net/caowei840701/article/details/8491836
《memcpy() vs memmove()》
http://stackoverflow.com/questions/4415910/memcpy-vs-memmove
我的memset:
void *memset(void *buffer, int c, int count){
void *reval = buffer;
while(count--){
(*(unsigned char *)buffer++) = (unsigned char)c;
}
return reval;
}
MSVC:
void * __cdecl memset (
void *dst,
int val,
size_t count
)
{
void *start = dst; #if defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC)
{
extern void RtlFillMemory( void *, size_t count, char ); RtlFillMemory( dst, count, (char)val );
}
#else /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */
while (count--) {
*(char *)dst = (char)val;
dst = (char *)dst + ;
}
#endif /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */ return(start);
}
完
走进C标准库(7)——"string.h"中函数的实现memcmp,memcpy,memmove,memset的更多相关文章
- 走进C标准库(8)——"string.h"中函数的实现相关字符串操作函数
我的strcat: char *strcat(char *dest,char *src) { char * reval = dest; while(*dest) dest++; while(*src) ...
- 走进C标准库(6)——"string.h"中函数的实现memchr
我写的memchr: void *memchr(const void *buf, char ch, unsigned count){ unsigned ; while(*(buf++) != ch & ...
- 走进C标准库(3)——"stdio.h"中的getc和ungetc
接前文. 再来看看getc和ungetc的实现.在看这两个函数的实现之前,我们先来想一想这两个函数分别需要做的工作. int getc(FILE *stream) 说明:函数getc从stream指向 ...
- 走进C标准库(2)——"stdio.h"中的fopen函数
其他的库文件看起来没有什么实现层面的知识可以探究的,所以,直接来看stdio.h. 1.茶余饭后的杂谈,有趣的历史 在过去的几十年中,独立于设备的输入输出模型得到了飞速的发展,标准C从这个改善的模型中 ...
- 走进C标准库(4)——"stdio.h"中的putc
花了点时间把园子弄得好看了点,现在继续. 函数名: putc 功 能: 输出一字符到指定流中 用 法: int putc(int ch, FILE *stream); #define _putc_ ...
- 走进C标准库(5)——"stdio.h"中的其他部分函数
函数介绍来自:http://ganquan.info/standard-c/ 函数名: freopen 功 能: 替换一个流 用 法: FILE *freopen(char *filename, ...
- 走进C标准库(1)——assert.h,ctype.h
默默觉得原来的阅读笔记的名字太土了,改了个名字,叫做走进C标准库. 自己就是菜鸟一只,第一次具体看C标准库,文章参杂了对<the standard C library>的阅读和对源码的一些 ...
- 谈谈两种标准库类型---string和vector
两种最重要的标准库---string和vector string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列. 一.标准库 ...
- C++ Primer 第三章 标准库类型string运算
1. 标准库类型 string string表示可变长的字符序列,使用string必须首先包含string头文件.如何初始化类的对象是由类本身决定的. int n; string s1;//默认初始化 ...
随机推荐
- JS赋值传递的问题
根据值的类型是基本类型值还是复杂类型的值在传递时会有不同. JS函数的参数传递是按值传递,基本类型值传递的是副本,复杂类型值传递的是引用.从而会影响原来的值,不会改变原来的复制前的引用. functi ...
- 模拟app上商品详情点击图片放大并且可以切换大图
主要使用swiper插件,这里使用各小技巧,就是用两个swiper容器,点击一个小图容器,去让大图容器展示出来 小图容器 <div class="q_banner"> ...
- CmdParse
Procedure URPOSE Uses Dos,Crt; Const VersionNum = 'V1.0 BETA'; ProgNameStr = 'NEWPROJ.EXE'; ProgName ...
- TCP粘包分析与处理
http://www.cnblogs.com/liyux/p/5594423.html http://www.cnblogs.com/liyux/p/5603826.html
- android TextView 带滚动条,和ScrollView 用法(暂时觉得ScrollView滑动速度比较快)
本来是想做一个显示文字信息的,当文字很多时View的高度不能超过一个固定的值,当文字很少时View的高度小于那个固定值时,按View的高度显示.因为ScrollView没有maxHeight,无法满足 ...
- js获得url内的参数
/** * js获得url内的参数 * 返回值: string or undefined * 使用方法:$_GET['from'] */ var $_GET = (function() { var s ...
- AndroidUI 引导页面的使用
一个应用程序都少不了欢迎页面和引导页面,本文主要讲如何制作一个引页面: 首页所有的目录结构: 新建Welcome引导页面和Activity: <RelativeLayout xmlns:andr ...
- 全国计算机等级考试二级教程-C语言程序设计_第14章_结构体、共用体和用户定义类型
函数的返回值是结构体类型 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> struct ...
- IEnumerable和IEnumerator 详解 【转】
初学C#的时候,老是被IEnumerable.IEnumerator.ICollection等这样的接口弄的糊里糊涂,我觉得有必要切底的弄清楚IEnumerable和IEnumerator的本质. 下 ...
- POJ1042 Gone Fishing
采用贪心策略. 假设他从1湖泊走到x 湖泊,这还剩下 h*12 - sigma(T1--Tx-1).(单位时间为5分钟).然后再用剩下的时间去钓1-x的湖泊的鱼. 每次都选择最多鱼的湖泊钓. code ...