5.strcpy函数
*简单使用
strcpy:string copy
翻译:
复制字符串
复制由source指向的C字符串到由destionation指向的数组中,包括\0(终止0字符)(在\0那里停止复制)
为了防止溢出,由destionation指向的数组的空间大小必须足够大,以至于能包含作为source的C字符串(含\0),而且不应该覆盖source的内存
参数
destination:指向将要复制内容的destination数组的指针
source:要被复制的C字符串
返回值
destination已经被返回(目标空间的起始地址)
cpp
char * strcpy ( char * destination, const char * source );
解释:strcpy(目标,源头);//目标和源头都是char*类型
strcpy(目标,源头);类似汇编的movsb和movsw
汇编中通常以rep和movsb或rep和movsw结合的方式来批量转移字符
movsb(move string byte)
movsw(move string word)
这两个指令都是从DS:SI地址处的数据传送到ES:DI地址处的数据
8086汇编代码示例
(用DOSBox的masm编译)
TypeScriptassume cs:code ;定义源头数据段,以byte形式填写,source为数据段的标号 source segment db 'H','e','l','l','o',' ','W','o','r','l','d','!' source ends ;为目标数据段留空间,以byte形式填写,destination为数据段的标号 destination segment destination: db 0,0,0,0,0,0,0,0,0,0,0,0,0 destination ends code segment start: mov ax,source mov ds,ax ;ds为source段的段地址 mov ax,destionation mov es,ax ;es为destination段的段地址 cld ;设置正方向传输 xor si,si ;si=0 xor di,di ;di=0 mov cx,12 ;设置循环次数为12(Hello World刚好12个字符) rep movsb ;重复12次传送 每执行一次该指令,si和di自动+1,cx自动-1 code ends end
注意:上面的**;** 为注释符号
C代码示例
cpp
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>string头文件包含strcpy
int main()
{
char arr1[] = { "Hello World!"};
char arr2[20] = { 0 };
strcpy(arr2, arr1);//注意\0也复制
printf("%s", arr2);
return 0;
}
由于arr1和arr2代表数组首元素的地址,因此可以使用strcpy
注意: 1.arr2要预留足够的空间!
2.注意字符串结束标志\0也复制,而且是复制结束的标志!!!在使用的过程中防止越界访问!
3.目标空间必须可以修改(如常量字符串不可修改)
*模拟实现
设计一个函数sim_strcpy
destination简写为dest source简写为src
cpp
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void sim_strcpy(char* dest, char* src)
{
while (*src != '\0')
{
*dest = *src;//解引用,字符复制
dest++;//指针移动
src++;//指针移动
}//字符串结尾的\0没有复制,因此要另加一行
*dest = *src;
}
int main()
{
char arr1[] = { "Hello World!"};
char arr2[20] = { 0 };
//像strcpy一样设置两个参数
sim_strcpy(arr2, arr1);
printf("%s", arr2);
return 0;
}
*优化
01.简化代码1
cpp
*dest = *src;
dest++;
src++;
可以直接写为
cpp
*dest++ = *src++;
因此为
cpp
while (*src != '\0')
{
*dest++ = *src++;
}//字符串结尾的\0没有复制,因此要另加一行
*dest = *src;
可以看到改变前后的汇编指令没有差别,除了最后三行
02.简化代码2
直接写为
cpp
while (*dest++ = *src++)//先复制,再判断
{
}
先复制一个字符,如果表达式的结果为真,即复制的该字符不为\0,则继续循环,否则结束循环
03.继续修改代码
发现sim_str函数和strcpy有一处不像的地方4
strcpy的返回类型为char*,而sim_strlen返回类型为void
因此改为
cpp
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
char* sim_strcpy(char* dest, char* src)
{
char* ret = dest;//存储目标空间的起始地址
while (*dest++ = *src++)
{
}
return ret;
}
int main()
{
char arr1[] = { "Hello World!"};
char arr2[20] = { 0 };
//像strcpy一样设置两个参数
char* ret = sim_strcpy(arr2, arr1);
printf("%s", ret);//从ret地址处开始,向后以%s打印
return 0;
}