(1) strcpy/strcat strncpy/strncat 比较
① 复制:
a . char* strcpy( char* dest, char* src ) ;
// 复制 src 到 dest 字符串中; src 结束的标志是 ’/0’
i 测试:
char* p="how are you ?";
char name[20]="ABCDEFGHIJKLMNOPQRS";
strcpy(name, p);
结果: // 正确! name=” how are you ?” , 因为 p 包含结束符 ’/0’
ii 测试:
char src[10];
src[0] = ‘A’;
src[1] = ‘L’;
src[2] = ‘I’;
char name[20]="ABCDEFGHIJKLMNOPQRS";
strcpy(name, src);
结果: // 不确定! name 值不确定 , src 结束符不确定在哪儿
若: memset( src, 0, sizeof(src) ); 或者 src[3] = ‘/0’ ,即确定结束符,则复制结果正确
b. char* strncpy( char* dest, char* src, int n );
// 复制 src 的前 n 个字符到 dest 中;如果前 n 个字符没有结束符,则结尾不会有结束符:
i . 测试:
char* p="how are you ?";
char name[20]="ABCDEFGHIJKLMNOPQRS";
strncpy(name, p , strlen(p)+1 );
结果: // 正确! name=” how are you ?” 包含结束符
若: strncpy(name, p , strlen(p) );
结果: // 错误! name=” how are you ?NOPQRS” 因为未复制结束符
name[strlen(p)+1] = ‘/0’; // 正确: name=” how are you ?”
ii . 测试:
char src[50];
src[0] = ‘A’;
src[1] = ‘L’;
src[2] = ‘I’;
char name[20]="ABCDEFGHIJKLMNOPQRS";
strncpy(name, src , 3);
name[4] = ‘/0’;
结果: // 正确! name=” how are you ?”
若: char* src = “HELLO WORLD”;
char des[1024];
strncpy( des, src, 1024 );
结果: // 正确! des=” HELLO WORLD +’/0’+…+ 将近 1000 个 ’/0’”
// 结论: strncpy 指定了 copy 的长度,避免了 strcpy 一直往后找 ’/0’ 的情况,避免了内存越界;
② 字符串连接:
a. char* strcat( char*dest, char* src );
// 复制 src 到 dest 的末尾
b. char* strncat( char* dest, char* src, int n );
// 复制 src 前 n 个字符到 dest 末尾,然后加 ’/0’ ;若 n>strlen(src) ,则 copy 整个 src ;
c . 越界:
测试:
char* p="how are you ?";
char name[20]="ABCDEFGHIJKLMNOPQRS";
strcat( name, p );
结果: // 错误! name=”ABCDEFGHIJKLMNOPQRShow are you ?” 越界,造成相邻内存被覆盖
测试:
char* p="how are you ?";
char name[20]="ABCDEFGHIJKLMNOPQRS";
strncat( name, p , strlen(p) ); //code ①
结果: // 错误! name=”ABCDEFGHIJKLMNOPQRShow are you ?” 越界,造成相邻内存被覆盖
修改 code ①为: strncat( name, p, sizeof(name)-strlen(name)-1 );
结果: // 正确! name=”ABCDEFGHIJKLMNOPQRS” ,无内存越界
(2) strlcpy/strlcat
① size_t strlcpy(char *dst, const char *src, size_t size);
② size_t strlcat(char *dst, const char *src, size_t size);
③ 两个函数均返回最终字符串长度,若返回长度 >sizeof(dst) ,则发生了截断,需要新增字符串缓存;同时 strlcpy 不会像 strncpy 那样有多余的 ’/0’ ,比 strncpy 效率要高
测试:
char name[20]="ABCDEFGHIJKLMNOPQRS";
char str[5];
int len = strlcpy( str, name, sizeof(str) );
if( len > sizeof(str) ){
printf( “ 产生截断 /n” );
}
结果: //str = “ABCD”; 若想判断是否截断,查看 strlcpy 返回值
测试:
char* p="how are you ?";
char name[20]="ABCDEFGHIJKLMNOPQRS";
int len = strlcat( name, p, sizeof(name) );
if( len > sizeof(name) ){
printf(“Array too short!/n”);
}
结果: //name = “ ABCDEFGHIJKLMNOPQRS ”; len(32) > sizeof(name)(20)
// 避免了内存覆盖
源代码:
strlcpy/strlcat 应用情况:
用于处理固定大小的 C 字符串;如果写的字符串支持动态分配的,任意大小的缓冲区,那就需要考虑看一下源码了, O( ∩ _ ∩ )O~