CherieLi Student

字符串复制与缓冲区复制

2019-10-18
CherieLi

1.strlen函数与sizeof关键字

strlen功能:计算给定字符串的长度,不包括‘\0’

strlen是一个函数,参数是char *

sizeof是关键字,取字节运算符

sizeof功能:返回一个对象或者类型所占的内存字节数

str.length()和str.size() 是求string类型对象的成员函数

#include <cstring>
#include <iostream>
#include <stdio.h>
using namespace std;
#define test "test string";
int main() {
  char *s = "test string"; //warning: deprecated conversion from string constant to ‘char*’
  cout << "strlen(s)=" << strlen(s) << endl; //strlen(s)=11
  cout << "sizeof(s)=" << sizeof(s) << endl; //sizeof(s)=8
  cout << endl;

  char mystr[100] = "test string";
  cout << "strlen(mystr)=" << strlen(mystr) << endl; //strlen(mystr)=11
  cout << "sizeof(mystr)=" << sizeof(mystr) << endl; //sizeof(mystr)=100
  cout << endl;

  char ss[] = "test string";
  cout << "strlen(ss)=" << strlen(ss) << endl; //strlen(ss)=11
  cout << "sizeof(ss)=" << sizeof(ss) << endl; //sizeof(ss)=12
  cout << endl;

  char *p = mystr;
  cout << "strlen(p)=" << strlen(p) << endl; //strlen(p)=11
  cout << "sizeof(p)=" << sizeof(p) << endl; //sizeof(p)=8
  cout << endl;

  string cur = "test string";
  cout << "strlen(cur)=" << strlen(cur.c_str()) << endl; //strlen(cur)=11
  cout << "cur.size()=" << cur.size() << endl; //cur.size()=11
  cout << "cur.length()=" << cur.length() << endl; //cur.length()=11
  cout << "sizeof(cur)=" << sizeof(cur) << endl; //sizeof(cur)=8
  cout << endl;

  string now = test;
  cout << "strlen(now)=" << strlen(now.c_str()) << endl;//strlen(now)=11
  cout << "now.size()=" << now.size() << endl;//now.size()=11
  cout << "now.length()=" << now.length() << endl;//now.length()=11
  cout << "sizeof(now)=" << sizeof(now) << endl;//sizeof(now)=8
  cout << endl;
  return 0;
}

运行结果:

  1. strlen函数求得的字符串长度是从字符串第一个元素到第一个’\0’之间元素的个数(如果字符串中间有’\0’,则结果不是整个字符串的长度),同时不包括该’\0’

  2. sizeof求得的结果是存储该字符串的变量占用的空间大小,因而一定会包括’\0’.若’\0’后还有空余的空间,也会包含到结果里面

2.strcpy,strncpy, strncpy_s(字符串复制)

2.1 strcpy

char * strcpy ( char * destination, const char * source );

strcpy 是依据 “\0” 作为结束判断的,如果 destination 的空间不够,则会引起 buffer overflow。

  char str1[100];
  char *s = "test string";
  cout << "strlen(s)=" << strlen(s) << endl; //strlen(s)=11
  cout << "sizeof(s)=" << sizeof(s) << endl; //sizeof(s)=8
  strcpy(str1, s);
  cout << "strcpy str1:" << str1 << endl;  //strcpy str1:test string
  cout << "strlen(str1)=" << strlen(str1) << endl; //strlen(str1)=11
  cout << "sizeof(str1)=" << sizeof(str1) << endl; //sizeof(str1)=100
  cout << endl;

2.2 strncpy

char * strncpy ( char * destination, const char * source, size_t num );

strncpy要安全一些。

拷贝你指定的个数或者碰到’\0’,不验证源缓冲区长度,可能造成越界。

如果遇到空字符(’\0’),则空字符后面为原来的字符。

  char str2[100];
  char str3[10];
  char mystr[100] = "test string";
  cout << "strlen(mystr)=" << strlen(mystr) << endl;//strlen(mystr)=11
  cout << "sizeof(mystr)=" << sizeof(mystr) << endl;//sizeof(mystr)=100

  strncpy(str2, mystr, sizeof(str2));
  cout << "strncpy str2:" << str2 << endl;//strncpy str2:test string
  cout << "strlen(str2)=" << strlen(str2) << endl; //strlen(str2)=11
  cout << "sizeof(str2)=" << sizeof(str2) << endl; //sizeof(str2)=100

  strncpy(str3, mystr, 4);
  str3[4] = '\0';
  cout << "strncpy str3:" << str3 << endl; //strncpy str3:test
  cout << "strlen(str3)=" << strlen(str3) << endl;//strlen(str3)=4
  cout << "sizeof(str3)=" << sizeof(str3) << endl;//sizeof(str3)=10
  cout << endl;

2.3 strncpy_s

编译选项

g++ main.cpp -std=c++11 /home/lzy/code/taurus-root/src/3rdparty/securec/lib/libsecurec.a

头文件:#include “securec.h”

strncpy_s 不以零填充目标数组。这是转换既存代码到边界检查版本的常见错误源。

dest - 指向要复制到的字符数组的指针
src - 指向复制来源的字符数组的指针
count - 要复制的最大字符数
destsz - 目标缓冲区的大小
errno_t strncpy_s(char *restrict dest, rsize_t destsz,
                  const char *restrict src, rsize_t count);
  char str4[100];
  char str5[10];
  char ss[] = "test string";
  cout << "strlen(ss)=" << strlen(ss) << endl; //strlen(ss)=11
  cout << "sizeof(ss)=" << sizeof(ss) << endl; //sizeof(ss)=12

  strncpy_s(str4, sizeof(str4), ss, sizeof(ss)); 
  cout << "strncpy_s str4:" << str4 << endl; //strncpy_s str4:test string
  cout << "strlen(str4)=" << strlen(str4) << endl; //strlen(str4)=11
  cout << "sizeof(str4)=" << sizeof(str4) << endl; //sizeof(str4)=100

  strncpy_s(str5, 10, ss, 4);
  str5[4] = '\0';
  cout << "strncpy_s str5:" << str5 << endl; //strncpy_s str5:test
  cout << "strlen(str5)=" << strlen(str5) << endl; //strlen(str5)=4
  cout << "sizeof(str5)=" << sizeof(str5) << endl; //sizeof(str5)=10
  cout << endl;

3. memcpy与memcpy_s(缓冲区复制)

3.1 memcpy

memcpy:不理’\0’,只拷贝你指定的个数,故strcpy可以不指定字符串长度,实现整串copy,而memcpy必定要指定长度。

void * memcpyvoid * destconst void * srcsize_t count;
  char str6[100];
  char str7[4];
  char *p = mystr;
  cout << "strlen(p)=" << strlen(p) << endl;  //strlen(p)=11
  cout << "sizeof(p)=" << sizeof(p) << endl; //sizeof(p)=8

  memcpy(str6, p, strlen(p) + 1); 
  cout << "memcpy str6:" << str6 << endl; //memcpy str6:test string
  cout << "strlen(str6)=" << strlen(str6) << endl; //strlen(str6)=11
  cout << "sizeof(str6)=" << sizeof(str6) << endl; //sizeof(str6)=100

  memcpy(str7, p, 4);
  cout << "memcpy str7:" << str7 << endl; //memcpy str7:test
  cout << "strlen(str7)=" << strlen(str7) << endl; //strlen(str7)=4
  cout << "sizeof(str7)=" << sizeof(str7) << endl; //sizeof(str7)=4
  cout << endl;

3.2 memcpy_s

count 大于 destsz (会发生缓冲区溢出)

dest - 指向要复制的对象的指针
destsz - 目标中要修改的最大字节数(典型地为目标对象的大小)
src - 指向复制来源对象的指针
count - 复制的字节数
errno_t memcpy_s( void *restrict dest, rsize_t destsz,
                  const void *restrict src, rsize_t count );
char str8[100];
  char str9[4];
  char str10[4];
  string cur = "test string";
  string cur2 = "ab";
  cout << "strlen(cur)=" << strlen(cur.c_str()) << endl;//strlen(cur)=11
  cout << "cur.size()=" << cur.size() << endl; //cur.size()=11
  cout << "cur.length()=" << cur.length() << endl; //cur.length()=11
  cout << "sizeof(cur)=" << sizeof(cur) << endl; //sizeof(cur)=8

  memcpy_s(str8, sizeof(str8), cur.c_str(), strlen(cur.c_str()) + 1);
  cout << "memcpy_s str8:" << str8 << endl; //memcpy_s str8:test string
  cout << "strlen(str8)=" << strlen(str8) << endl; //strlen(str8)=11
  cout << "sizeof(str8)=" << sizeof(str8) << endl; //sizeof(str8)=100

  memcpy_s(str9, 4, cur.c_str(), 4);
  cout << "memcpy_s str9:" << str9 << endl; //memcpy_s str9:test
  cout << "strlen(str9)=" << strlen(str9) << endl; //strlen(str9)=4
  cout << "sizeof(str9)=" << sizeof(str9) << endl; //sizeof(str9)=4

  memcpy_s(str10, 4, cur.c_str(), 3);
  cout << "memcpy_s str10:" << str10 << endl;  //memcpy_s str10:tes
  cout << "strlen(str10)=" << strlen(str10) << endl; //strlen(str10)=3
  cout << "sizeof(str10)=" << sizeof(str10) << endl; //sizeof(str10)=4
  cout << endl;

上一篇 gcc编译

下一篇 开发者测试

Comments

Content