字符串拷贝函数memcpy和strncpy以及snprintf 的性能比较

问题:
函数memcpy(dest, src, sizeof(dest))、strncpy(dest, src, sizeof(dest))和snprintf(dest, sizeof(dest), "%s", src)都可以将src字符串中的内容拷贝到dest字符串中。
哪一种方式效率最高呢?
就是说,哪种方式性能最好呢?
解决办法:
1. 建立三个文件test_memcpy.c,test_strncpy.c和test_snprintf.c:
文件test_memcpy.c:


代码如下:

david@u1110-hp:~/wrk/tmp/cstring$ cat test_memcpy.c
#include <string.h>
int main(){
 char src[] = "1234567890";
 char dest[2048];
 int len = 0;
 for(int i = 0; i < 10000000; ++i){
  memset(dest, 0, sizeof(dest));
  len = strlen(src);
  len = sizeof(dest) - 1 > len? len: sizeof(dest) -1;
  memcpy(dest, src, len);
  dest[len] = '\0';
 }
 return 0;
}

文件test_strncpy.c:


代码如下:

#include <string.h>
int main() {
 char src[] = "1234567890";
 char dest[2048];
 int len = 0;

for(int i = 0; i < 10000000; ++i) {
  memset(dest, 0, sizeof(dest));
  strncpy(dest, src, sizeof(dest));
 }

return 0;
}

文件test_snprintf.c:


代码如下:

#include <stdio.h>
#include <string.h>
int main() {
 char src[] = "1234567890";
 char dest[2048];
 int len = 0;

for(int i = 0; i < 10000000; ++i) {
  memset(dest, 0, sizeof(dest));
  snprintf(dest, sizeof(dest), "%s", src);
 }

return 0;
}

2. 分别编译三个文件:


代码如下:

david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -o test_memcpy test_memcpy.c
david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -o test_strncpy test_strncpy.c
david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -o test_snprintf test_snprintf.c

3. 没有优化的情况下不同函数消耗时间对比:


代码如下:

david@u1110-hp:~/wrk/tmp/cstring$ time ./test_strncpy
real 0m16.472s
user 0m16.309s
sys 0m0.036s
david@u1110-hp:~/wrk/tmp/cstring$ time ./test_snprintf
real 0m6.106s
user 0m6.100s
sys 0m0.000s
david@u1110-hp:~/wrk/tmp/cstring$ time ./test_memcpy
real 0m4.179s
user 0m4.144s
sys 0m0.000s
david@u1110-hp:~/wrk/tmp/cstring$

从上面运行结果可以看出:没有任何优化的情况下,memcpy()和strncpy()性能相差4倍,snprintf()和strncpy()性能相差约2.5倍。

4.采用O3优化情况下不同函数消耗时间对比:


代码如下:

david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -O3 -o test_snprintf test_snprintf.c
david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -O3 -o test_strncpy test_strncpy.c
david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -O3 -o test_memcpy test_memcpy.c
david@u1110-hp:~/wrk/tmp/cstring$

代码如下:

david@u1110-hp:~/wrk/tmp/cstring$ time ./test_strncpy
real 0m16.178s
user 0m16.161s
sys 0m0.000s
david@u1110-hp:~/wrk/tmp/cstring$ time ./test_snprintf
real 0m6.242s
user 0m6.032s
sys 0m0.056s
david@u1110-hp:~/wrk/tmp/cstring$ time ./test_memcpy
real 0m3.567s
user 0m3.436s
sys 0m0.012s
david@u1110-hp:~/wrk/tmp/cstring$

从上面运行结果可以看出:采用O3优化后,memcpy()和strncpy()性能相差近5倍,snprintf()和strncpy()性能相差基本不变约2.5倍。

5. 性能对比结论:
在需要用到字符串拷贝函数的时候,永远不要使用strncpy(),无论什么时候都用snprintf()来代替,而memcpy()是性能更好的实现方式。
strlen+memcpy也是linux内核的实现方式。

6. 意外收获结论:
将上述三个文件中的memset()改为用bzero()来实现数组的清零操作。
使用O3来进行优化,三个函数的耗时时间如下:


代码如下:

david@u1110-hp:~/wrk/tmp/cstring$ time ./test_strncpy
real 0m14.395s
user 0m13.929s
sys 0m0.092s
david@u1110-hp:~/wrk/tmp/cstring$ time ./test_snprintf
real 0m3.785s
user 0m3.772s
sys 0m0.000s
david@u1110-hp:~/wrk/tmp/cstring$ time ./test_memcpy
real 0m1.241s
user 0m1.236s
sys 0m0.004s
david@u1110-hp:~/wrk/tmp/cstring$

结论:仅仅换了一个清零函数,使得memcpy()和strncpy()的性能差别达到约12倍,而snprintf()和strncpy()的性能差别也达到约4倍。
就清零操作来说,bzero()远比memset()更高效。

(0)

相关推荐

  • 详解C语言中strcpy()函数与strncpy()函数的使用

    C语言strcpy()函数:复制字符串 头文件:#include <string.h> 定义函数: char *strcpy(char *dest, const char *src); 函数说明:strcpy()会将参数src 字符串拷贝至参数dest 所指的地址. 返回值:返回参数dest 的字符串起始地址. 附加说明:如果参数 dest 所指的内存空间不够大,可能会造成缓冲溢出(buffer Overflow)的错误情况,在编写程序时请特别留意,或者用strncpy()来取代. 范例 #i

  • C语言中字符串常用函数strcat与strcpy的用法介绍

    strcpy原型声明:extern char *strcpy(char* dest, const char *src);头文件:#include <string.h>功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串.返回指向dest的指针.函数实现: 复制代码 代码如下: /********************** * C语言标准库函数strcpy的一种典型的工业级的

  • 字符串拷贝函数memcpy和strncpy以及snprintf 的性能比较

    问题:函数memcpy(dest, src, sizeof(dest)).strncpy(dest, src, sizeof(dest))和snprintf(dest, sizeof(dest), "%s", src)都可以将src字符串中的内容拷贝到dest字符串中.哪一种方式效率最高呢?就是说,哪种方式性能最好呢?解决办法:1. 建立三个文件test_memcpy.c,test_strncpy.c和test_snprintf.c:文件test_memcpy.c: 复制代码 代码如下

  • c++面试题字符串拷贝函数示例

    复制代码 代码如下: #include<iostream>using namespace std; //字符串拷贝函数char * sCpy(char *strDest, char *strSource){    _ASSERT((strDest != NULL) && (strSource!=NULL));    char *d = strDest;              //获取dest的当前位置    char *s = strSource;            /

  • 超详细的c语言字符串操作函数教程

    目录 一,常量指针与指针常量 二,字符串长度问题 三,c语言中的字符串拷贝函数 1) strcpy() 2), strncpy() 3), strcat() 4), strncat() 5), strcmp() 6), strncmp() 7), sprintf() 8) sscanf() 9) strchr() 10), strstr() 11) strtok() 总结 我们知道,c/c++之所以使用起来灵活,很大原因归因于它能够它对能够对内存的直接操作,所以本文我主要讲述一下c中的字符串操作

  • C语言进阶教程之字符串&内存函数

    目录 前言: 一.求字符串长度 strlen strlen函数的模拟实现 二.长度不受限制的字符串函数 strcpy strcpy函数的模拟实现 strcat strcat函数的模拟实现 strcmp strcmp函数的模拟实现 三.长度受限制的字符串函数 strncpy strncpy函数的模拟实现 strncat strncat函数的模拟实现 strncmp strncmp函数的模拟实现 四.字符串查找 strstr strstr函数的模拟实现 strtok strtok函数的模拟实现 五.

  • C,C++中常用的操作字符串的函数

    小小的做一个总结 函数名: stpcpy 功 能: 拷贝一个字符串到另一个,遇到'\0'时停止拷贝,destin要有足够大的空间 用 法: char *stpcpy(char *destin, char *source);   函数名: strcat 功 能: 字符串拼接函数,注意,destin要有足够大的空间 用 法: char *strcat(char *destin, char *source); 函数名: strchr 功 能: 在一个串中查找给定字符的第一个匹配之处,找不到返回NULL

  • C语言实现字符串操作函数的实例

    C语言实现字符串操作函数的实例 在编写程序的过程中,我们经常使用到一些字符串函数,例如求字符串长度,拷贝字符串--,这些函数都在C标准库中存在,我们可以直接使用.但我们还需要掌握这些函数的实现方法,今天来看看一些常用的字符串操作函数的实现方法. 1.strlen strlen是用来求字符串长度的函数,字符串长度就是它所包含的字符个数. 今天给大家介绍三种实现strlen函数的方法 (1)定义一个计数器count //方式一:定义一个计数器 size_t my_strlen(const char

  • Linux C字符串替换函数实例详解

    Linux C字符串替换函数实例详解 最近学习linux 的基础编程知识,字符串替换函数,在网上找下资料,觉得这篇文章写的不错,记录下来,和大家分享一下: 实例代码: #include <stdio.h> #include <string.h> #include <stdlib.h> /** * * @author: cnscn@163.com * @reference: lovesnow1314@http://community.csdn.net/Expert/Top

  • 从头学习C语言之字符串处理函数

    目录 字符串处理函数: 存放和使用字符串: 获取字符串长度:strlen 示例: 拷贝字符串:strcpy和strncpy 示例: strncpy: 示例: 连接字符串:strcat和strncat 示例: 比较字符串:strcmp和ctrncmp strncmp和strcmp和区别: 示例: 总结 字符串处理函数: 存放和使用字符串: 字符串常量:“fishc”,“小甲鱼”,“鱼C工作室”字符数组: 获取字符串长度:strlen 用法:strlen(str) 注意: 这个函数获得的是长度(不带

  • 详解C语言内核字符串拷贝与比较

    在上一篇文章<驱动开发:内核字符串转换方法>中简单介绍了内核是如何使用字符串以及字符串之间的转换方法,本章将继续探索字符串的拷贝与比较,与应用层不同内核字符串拷贝与比较也需要使用内核专用的API函数,字符串的拷贝往往伴随有内核内存分配,我们将首先简单介绍内核如何分配堆空间,然后再以此为契机简介字符串的拷贝与比较. 首先内核中的堆栈分配可以使用ExAllocatePool()这个内核函数实现,此外还可以使用ExAllocatePoolWithTag()函数,两者的区别是,第一个函数可以直接分配内

  • C语言内存函数 memcpy,memmove ,memcmp

    目录 一.memcpy函数 1.用法 2.模拟实现memcpy函数 二.memmove函数 1.用法 2.模拟实现memmove函数 三.memcmp函数 1.用法 2.模拟实现memcmp函数 一.memcpy函数 1.用法 memcpy表示内存函数,用法跟strcpy差不多, 都是作为拷贝函数存在strcpy只能用于字符串函数,而memcpy函数可以使用任意类型在使用任意类型时,肯定用到的参数是voidvoid* memcpy(const void *dest,const void *src

随机推荐