一直以为strncpy效率优于snprintf. 无意中在网上看到snprintf效率大于strncpy,颇感震惊. 网址如下:
http://blog.csdn.net/wavemoon/archive/2009/12/06/4952904.aspx
后自己编码测试了下,发现情况复杂,并不是如此.
现在帖上我的测试:
环境: linux
编译器:g++
代码:
- #include <iostream>
- #include <string.h>
- #include <stdlib.h>
- #include "sys/time.h"
- const int LOOP_COUNT = 10000;
- class RecTime
- {
- public:
- RecTime()
- {
- gettimeofday(&m_stBegin, NULL);
- }
- ~RecTime()
- {
- gettimeofday(&m_stEnd, NULL);
- int iUsedMs = (m_stEnd.tv_sec - m_stBegin.tv_sec)*1000 +
- (m_stEnd.tv_usec-m_stBegin.tv_usec + 999) / 1000;
- std::cout << "time used: " << iUsedMs << std::endl;
- }
- private:
- struct timeval m_stBegin;
- struct timeval m_stEnd;
- };
- void test_strncpy(char* pDst, int iDstLen, char* pSrc)
- {
- RecTime _time_record;
- for(int i=0; i<LOOP_COUNT; i++)
- {
- if(pDst != strncpy(pDst, pSrc, iDstLen))
- {
- std::cout << "fatal error, strncpy failed.";
- exit(1);
- }
- }
- return ;
- }
- void test_strncpy_withnull(char* pDst, int iDstLen, char* pSrc)
- {
- RecTime _time_record;
- for(int i=0; i<LOOP_COUNT; i++)
- {
- if(pDst != strncpy(pDst, pSrc, iDstLen))
- {
- std::cout << "fatal error, strncpy failed.";
- exit(1);
- }
- pDst[iDstLen - 1] = 0;
- }
- return ;
- }
- void test_snprintf(char* pDst, int iDstLen, char* pSrc)
- {
- RecTime _time_record;
- for(int i=0; i<LOOP_COUNT; i++)
- {
- if(0 > snprintf(pDst, iDstLen, "%s", pSrc))
- {
- std::cout << "fatal error, snprintf failed.";
- exit(1);
- }
- }
- return ;
- }
- int main(int argc, char* argv[])
- {
- char szDst[1024] = {0};
- char szSrc[1024] = {0};
- memset(szSrc, '1', sizeof(szSrc)-1);
- szSrc[sizeof(szSrc)-1] = 0;
- char* pDst = szDst;
- int iDstSize = sizeof(szDst);
- char* pSrc = szSrc;
- int iSrcSize = sizeof(szSrc);
- std::cout << "copy " << iSrcSize << " to "<< iDstSize << std::endl;
- std::cout << "snprintf ";
- test_snprintf(pDst, iDstSize, pSrc);
- std::cout << "strncpy ";
- test_strncpy(pDst, iDstSize, pSrc);
- /
- return 0;
- }
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include "sys/time.h"
const int LOOP_COUNT = 10000;
class RecTime
{
public:
RecTime()
{
gettimeofday(&m_stBegin, NULL);
}
~RecTime()
{
gettimeofday(&m_stEnd, NULL);
int iUsedMs = (m_stEnd.tv_sec - m_stBegin.tv_sec)*1000 +
(m_stEnd.tv_usec-m_stBegin.tv_usec + 999) / 1000;
std::cout << "time used: " << iUsedMs << std::endl;
}
private:
struct timeval m_stBegin;
struct timeval m_stEnd;
};
void test_strncpy(char* pDst, int iDstLen, char* pSrc)
{
RecTime _time_record;
for(int i=0; i<LOOP_COUNT; i++)
{
if(pDst != strncpy(pDst, pSrc, iDstLen))
{
std::cout << "fatal error, strncpy failed.";
exit(1);
}
}
return ;
}
void test_strncpy_withnull(char* pDst, int iDstLen, char* pSrc)
{
RecTime _time_record;
for(int i=0; i<LOOP_COUNT; i++)
{
if(pDst != strncpy(pDst, pSrc, iDstLen))
{
std::cout << "fatal error, strncpy failed.";
exit(1);
}
pDst[iDstLen - 1] = 0;
}
return ;
}
void test_snprintf(char* pDst, int iDstLen, char* pSrc)
{
RecTime _time_record;
for(int i=0; i<LOOP_COUNT; i++)
{
if(0 > snprintf(pDst, iDstLen, "%s", pSrc))
{
std::cout << "fatal error, snprintf failed.";
exit(1);
}
}
return ;
}
int main(int argc, char* argv[])
{
char szDst[1024] = {0};
char szSrc[1024] = {0};
memset(szSrc, '1', sizeof(szSrc)-1);
szSrc[sizeof(szSrc)-1] = 0;
char* pDst = szDst;
int iDstSize = sizeof(szDst);
char* pSrc = szSrc;
int iSrcSize = sizeof(szSrc);
std::cout << "copy " << iSrcSize << " to "<< iDstSize << std::endl;
std::cout << "snprintf ";
test_snprintf(pDst, iDstSize, pSrc);
std::cout << "strncpy ";
test_strncpy(pDst, iDstSize, pSrc);
/
return 0;
}
输出:
copy 102400 to 102400
snprintf time used: 455
strncpy time used: 938
copy 10240 to 10240
snprintf time used: 42
strncpy time used: 94
copy 1024 to 1024
snprintf time used: 6
strncpy time used: 10
copy 64 to 64
snprintf time used: 2
strncpy time used: 1
copy 8 to 8
snprintf time used: 2
strncpy time used: 1
copy 1024 to 10240
snprintf time used: 6
strncpy time used: 104
copy 10240 to 1024
snprintf time used: 1234
strncpy time used: 10
copy 24 to 1024
snprintf time used: 2
strncpy time used: 11
copy 1024 to 24
snprintf time used: 136
strncpy time used: 1
分析:
1. 在源串长度和目标串长度一样大的情况下,效率几乎相同. 在一个数量级上. 因为在linux下snprintf末尾会有'\0'.所以这时推荐使用snprintf
2. 源串长度 < 目标串长度 snprintf效率领先一个级别, 这时推荐使用snprintf
3. 源串长度 > 目标串长度 strncpy效率领先一个级别, 这时推荐使用strncpy
结论:
1.在源串长度 远大于 目标串长度(至少几倍). 且效率重要的时候. 考虑使用strncpy(这时别忘了在末尾加'\0')
2.其他情况推荐使用snprintf