Bootstrap

sprintf与snprintf 区别

/sprintf的用法
{
char buffer[10]; //定义一个只有10个字节空间的buffer数组
const int a = 12345; //定义一个int型的常量
const char *msg = “012345678901234567890”; //定义一个长度为20字节的字符串常量

sprintf(buffer, "%d", a); //将a变量按int类型打印成字符串,输出到buffer中
/*
输出分析:
输出结果: buffer="12345"
因为最后输出的buffer内容长度不超过10字节,所以此时sprintf操作是没有溢出风险的
*/

sprintf(buffer, "%d+%s", a, msg); //将a变量和msg字符串通过“+”连接成一个字符串
/*
输出分析:
由于buffer只有10个字节空间,而sprintf在执行字符串格式化输出的时,并不知道buffer的真实长度,
所以它会将"12345+012345678901234567890"这整个字符串都拷贝到buffer空间上,这就导致了buffer存储空间溢出了。
从存储位置上分析,我们知道buffer空间属于一个栈空间,在它自己的10字节之外的空间很明显是其他栈变量的存储空间,
一旦sprintf将10字节外的其他空间也操作了,这就有可能破坏了其他栈变量的内容,这有可能是致命的。
*/

}

//snprintf的用法
{
char buffer[10]; //定义一个只有10个字节空间的buffer数组
const int a = 12345; //定义一个int型的常量
const char *msg = “012345678901234567890”; //定义一个长度为20字节的字符串常量

snprintf(buffer, sizeof(buffer), "%d", a); //将a变量按int类型打印成字符串,输出到buffer中
/*
输出分析:
输出结果: buffer="12345"
因为最后输出的buffer内容长度不超过10字节,所以snprintf操作是没有溢出风险的;
此种情况下,使用sprintf和snpintf都可以得到同样的结果,且都不会产生数组溢出。
*/

sprintf(buffer, sizeof(buffer), "%d+%s", a, msg); //将a变量和msg字符串通过“+”连接成一个字符串
/*
输出分析:
输出结果是: buffer="12345+0123",加上一个'\0'的字符串结束符,
刚好占用了buffer的10字节的存储空间,不存在任何的buffer溢出风险。而"0123"后面的字符串都被snprintf内部裁剪掉了,这就体现了snprintf操作安全的特性。
*/

}

;