关于操作字符串的安全函数,这些并非是C标准中的,是微软实现的,所以可能你在没有引入实现的情况下去运用,就会提示没有发现此定义类似提示,如下:
所以要把实现的函数引入,再用,如下:
将实现函数及头文件引入,然后进行使用,下面我们开始:
【函数1: memset_s】
【格式】
memset_s(dest, sizeof(dest), int n, sizeof(dest))
【功能】
初始化某一块指定长度(一般情况下为字符数组)的内存为n值,或者理解为:初始化内存内容为某一数值,也可以的
【入参】
dest:内存块地址
sizeof(dest):内存块总大小
n:要被初始化的值,一般情况下是0
sizeof(dest):要被初始化的内存长度
【返回值】
这里我们对这个返回值一般不关心,因为我们主要是初始化内存块,获得返回值对于我们来说也并没有什么太大的用,是作为返回给系统进行校验的,这个有兴趣的可以去查询下关于size_t,errno_t, rsize_t类型的定义和含义,我们这里主要介绍函数功能和使用
【test_code】
【总结】
这个memset_s函数比我们的void * memset(void *s, int c, size_t n);函数多了一个内存总长度的入参,在初始化时候,编译器会检验是否超过内存总长度,所以相对而言比较安全
【函数2: strncpy_s】
【格式】
char* strncpy_s(char *dest, sizeof(dest),char *src, strlen(src));
【功能】
向目的内存拷贝一定长度的字符串
【入参】
dest:目的地址
sizeof(dest):可拷贝大小
src:待拷贝的字符串
strlen(src):待拷贝的字符串有效长度
【test_code】
【总结】
我们可以看下:
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, int n);
char* strncpy_s(char *dest, sizeof(dest),char *src, strlen(src));
会发现其实后来的cp函数比原来的在长度和安全区做了更多的限定,所以才"安全"!
【函数3: strcat_s】
【格式】
errno_t strcat_s(char *strDest, size_t destMax, const char *strSrc);
【功能】
在一个字符串后面追加上另外一个字符串
【入参】
strDest:目的地址
destMax:目的地址最大容量
char:待操作的字符串
【返回值】
返回一个整数,0表示复制成功,返回非0值代表复制不成功,不同的值表示不同的错误,具体内容可以查阅MSDN手册
【test_code】
输出结果:
【总结】
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);
errno_t strcat_s(char *strDest, size_t destMax, const char *strSrc);
可以看出多了一个参数,长度限定
#include <stdio.h>
#include <string.h>
#include "./head/log.h"
int main()
{
char src[MAXS] = "I am okay!";
char dest[MAXS];
char *p = "hello";
memset(dest, 0, sizeof(dest));
//dest[MAXS] = "hello";只有在初始化时才可以这样赋值,后面只能用copy函数赋值
strncpy(dest, p, sizeof(char)*6);
LOGS(dest);
LOG();
strcat(dest, src);
LOGS(dest);
strncat(dest, src, sizeof(char)*10);
LOG();
LOGS(dest);
return SUCCESS;
}
输出:
hello
===============
helloI am okay!
===============
helloI am okay!I am okay!
/*strcat_s验证*/
void cats()
{
char dest[200] = "I am ...";
char src[] = "hello day";
LOGS(dest);//I am ...
strcat_s(dest, sizeof(dest), src);
LOG();
LOGS(dest);//I am ...hello day
}
int main()
{
char dest[MAXS];
char *str = "it is not a good idea in life!";
memset_s(dest, sizeof(dest), 0, sizeof(dest));
LOGS("str", str);
LOGS("dest", dest);
LOG();
strcat(dest, str);
LOGS("strcat_dest", dest);
memset(dest, 0, sizeof(dest));
strcat_s(dest, sizeof(dest), str);
LOG();
LOGS("strcat_s__dest", dest);
return SUCCESS;
}
【函数4: memcpy_s】
【格式】
errno_t memcpy_s(char *dest , size_t big , const char *src , size_t count);
【功能】
拷贝一定长度的字符串到目的内存dest
【入参】
dest:拷贝完成之后的字符串地址
big: dest的大小,一般都是sizeof(dest)
src:需要拷贝的字符串
count:需要拷贝的字符串长度
注意:big必须大于等于count,否则拷贝将出现中断。
【返回值】
返回一个整数,0表示复制成功,返回非0值代表复制不成功,不同的值表示不同的错误,具体内容可以查阅MSDN手册
【test_code】
【总结】
void *memcpy(void *destin, void *source, unsigned n);
errno_t memcpy_s(char *dest , size_t big , const char *src , size_t count);
还是多了个范围限定
【函数4: sscanf_s】
【格式】
int sscanf(const char *str, const char *format, ...);
int sscanf_s(const char *buffer, const char *format, ...)
【功能】
将字符或者数值赋予某个变量,这只是简单的一种用法而已
【入参】
buffer:原始数据
format:不定参数,以某种格式去把原始数据操作存储或者赋予新变量中,以备使用
【返回值】
整形,一般不用来做检验,没多大意义
【test_code】
char input[] = "42";
int number;
sscanf_s(input, "%d", &number, sizeof(number));
char input[] = "42";
int number;
sscanf(input, "%d", &number);
【总结】
可以看出sscanf_s比sscanf多了一个sizeof校验参数,对于操作的变量,所以更安全了哦
【函数4: snprintf_s】
【格式】
int snprintf(char *str, size_t size, const char *format, ...);
int snprintf_s(char *str, size_t size, size_t size-1, const char *format, ...);
【功能】
将字符串和数值组合成一个命令
【入参】
str:待操作的地址块
size:待操作的地址块的大小
size-1:允许被操作的地址块大小
format:不定参数,以某种格式去把数据赋值给地址块
【返回值】
整形,可以用了做检验,均可
#include <stdio.h>
int main() {
char buffer[20];
int num = 42;
// Format the data into the buffer
int num_chars_written = snprintf(buffer, sizeof(buffer), "The number is %d", num);
// Check if the operation was successful and print the result
if (num_chars_written < sizeof(buffer)) {
printf("Formatted string: %s\n", buffer);
} else {
printf("Buffer size too small to store the formatted string.\n");
}
return 0;
}
【test_code】
char buffer[20];
int num = 42;
// Format the data into the buffer
int num_chars_written = snprintf(buffer, sizeof(buffer), "The number is %d", num);
snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "The number is %d", num);
【总结】
可以看出snprintf_s比snprintf多了一个sizeof校验参数,对于操作的变量,所以更安全了哦
【函数5: fscnaf_s】
这个函数目前用的不多,所以就没有举例演示
【注意】
我们这里用到了多个文件编译,所以需要用Makefile,如下:
这里关于这个不做赘述,我的主页有关于这个的文章,大家有兴趣的可以去看下,就知道怎么会回事了。