学习函数时,学到了strcpy()函数,本来打算练习一番,没想到出现了一系列的错误。
首先介绍一下strcpy()函数:
strcpy()
函数是C语言中的一个字符串函数,用于将一个字符串复制到另一个字符串中。它的原型如下:
char *strcpy(char *dest, const char *src);
函数接受两个参数,dest
和src
,分别表示目标字符串和源字符串。dest
应该是一个足够大的字符数组,以容纳复制的字符串,而src
是要复制的字符串。
函数的作用是将src
指向的字符串复制到dest
指向的字符串中,包括字符串的终止符\0
。复制完成后,dest
将包含完整的src
内容。
需要注意的是,函数的返回值是一个指向目标字符串的指针。这意味着可以将strcpy()
的返回值直接赋给另一个字符指针变量。
使用strcpy()
函数时,需要确保目标字符串dest
有足够的空间来存储源字符串src
的内容,以防止缓冲区溢出。
然后我就用写了一个简单的代码,如下:
#include <stdio.h>
#include <string.h>
int main()
{
char source[] = "Hello";
char destination[5];
strncpy(destination, source);
printf("%s\n", destination);
return 0;
}
运行报错,如下所示:
然后右击strncpy点击“转到定义”可以看到:
这里看不太懂,于是我改用strncpy_s(destination, source);
结果同样会报错,如下:
于是,右击strncpy_s转到函数定义,显示如下:
发现与刚才的strcpy()
函数定义不太相同,strncpy_s()函数需要4个参数,所以错误中显示“用于调用的参数太少”,经过查找,发现4个参数的含义如下:
-
_Destination
:指向目标缓冲区的指针。这个缓冲区将用于存储源字符串的副本。_Out_writes_z_(_SizeInBytes)
:表示这是一个输出参数,用于指定目标缓冲区的大小(以字节为单位),并告诉静态分析工具检查缓冲区是否足够大。
-
_SizeInBytes
:目标缓冲区的大小(以字节为单位)。_In_
:表示这是一个输入参数,用于指定目标缓冲区的大小。
-
_Source
:指向源字符串的指针,用于复制到目标缓冲区。_In_reads_or_z_(_MaxCount)
:表示这是一个输入参数,用于指定源字符串的大小(以字符为单位),并告诉静态分析工具检查源字符串是否足够大。
-
_MaxCount
:要复制的最大字符数。_In_
:表示这是一个输入参数,用于指定要复制的最大字符数。
-
返回值:表示函数的执行状态。
errno_t
:这是一个代表错误码的类型。如果函数执行成功,则返回0。否则,返回一个非零错误码。
strncpy_s()
函数的作用是将源字符串的指定个数字符复制到目标字符串中,同时可以指定目标字符串和源字符串的大小。该函数的返回值为errno_t
类型,用于指示操作成功与否。
于是,我修改上述代码,如下所示:
#include <stdio.h>
#include <string.h>
int main()
{
char source[10] = "Hello";
char destination[5];
strncpy_s(destination, sizeof(destination), source, sizeof(source));
printf("%s\n", destination);
return 0;
}
结果报错,如下所示:
重新修改代码,改为strncpy_s(destination, sizeof(destination), source, sizeof(destination));
运行仍然报错,与上面的错误提示一样。
该错误是由于调用strcpy_s
函数时,目标缓冲区大小不足导致的。
解决方法有两种:
-
调整目标缓冲区的大小:将
destination
数组的大小增加到能够容纳源字符串的大小。例如,将char destination[5]
修改为char destination[10]
。 -
使用更安全的字符串函数:除了
strcpy_s
函数,C语言中还有其他一些更安全的字符串函数,如strncpy_s
。strncpy_s
函数可以指定要复制的最大字符数,以避免目标缓冲区溢出的问题。
如果不修改大小,就只能减少目标缓冲区的大小,如下所示,运行不会报错,但缺点是字符串复制不全
#include <stdio.h>
#include <string.h>
int main() {
char source[10] = "Hello";
char destination[5];
// 使用strncpy_s向destination复制source
// 目标缓冲区大小为5,复制的最大字符数为4
strncpy_s(destination, sizeof(destination), source, sizeof(destination) - 1);
printf("%s\n", destination);
return 0;
}
结果如下所示:
后来我想明白,为什么目标缓冲区的大小会不足,明明“Hello”只有5个字符。原因在于字符串的写入后面会隐藏一个字符‘\0’,这在我的另一篇文章讲解过:关于循环语句练习二-CSDN博客。所以source中存的是6个字符,所以会报错。
修改代码,如下所示:
#include <stdio.h>
#include <string.h>
int main() {
char source[] = "Hello";
char destination[10];
strncpy_s(destination, sizeof(destination), source, sizeof(destination) );
printf("destination = %s\n", destination);
printf("sizeof(source) = %d\n", sizeof(source));
return 0;
}
运行结果如下所示,我们也可以看到数组source 的大小确实是6.
至此, 函数strncpy_s()学习完毕!