C里安全的字符串拷贝 strncpy strcpy sprintf snprintf
2012-08-01 17:35
162 查看
C里操作字符串很高效,但也很麻烦。
1. char *
strcpy ( char * destination, const char * source );
最常用的函数,但是却不安全,原因在于,一是要destination有足够的空间,二是要保证source和destination指向的空间没有overlap。
2. int sprintf
( char * str, const char * format, ... );
也许要问,这个怎么用于字符串拷贝呢?可以这么用 sprintf(dest, "%s", src); 但是要调用者保证dest有足够的内存存放src。
3. char *
strncpy ( char * destination, const char * source, size_t num );
比起strcpy,多了个长度的控制。从source拷贝num个字符到destination。如果source里不够num字符怎么办呢?会补充0。
一个典型的用法是:
char buf[MAX];
strncpy(buf, src, MAX-1);
这段代码的本意是,一个长为MAX的buf,最多也就放MAX-1个字符,最后一个位置放‘\0'。因此最多能从src里拷贝MAX-1个字符,如果src里没这么多,剩余的填充0就是了。
但是这样做就安全了么?不是,如果src刚好MAX-1个字符。注意到strncpy只复制了MAX-1个字符,最后一个位置未知,有潜在的隐患。下段代码可以诠释:
#define MAX 4
char buf[MAX];
char* src="123";
memset(buf, 'x', MAX);
// solution 1. memset(buf, 0, MAX);
strncpy(buf, src, MAX-1);
// solution 2. buf[MAX-1] = '\0';
printf("%s\n", buf);
有两个办法可以解决:1. 调用strncpy之前memset为0,有点浪费。2. 在strncpy之后对最后一个字符赋值为0。
都可以,但不够优雅。
4. int snprintf( char *buffer, int buff_size, const char *format, ... );
用作字符串拷贝的用法:
char buf[MAX];
snprintf(buf, sizeof(buf), "%s", src);
即安全,又简洁。
你可能会关心:如果src的长度大于dest(buf)呢?这个是另外一个问题,这里需要的是安全的字符串拷贝,在C语言里,如果一个字符串指针指向的内存没有结尾字符'\0',是非常危险的。
snprintf会把buf的最后一个位置保留为'\0'。
关于返回值:如果当前buf够用,返回实际写入的字符数;如果不够用,返回将要写入的字符数。换句话说,返回值就是传入的字符数目。
假设当前的buf[4].
待写入 实际写入 返回值
12 12 2 够用
123 123 3 够用
1234 123 4 不够用
12345 123 5 不够用
sprintf/snprintf的另外一个用法:
itoa不是ANSI C或C++的一部分,可以变相的用sprintf来代替:
sprintf(str,"%d",value) 转换为十进制数值。
sprintf(str,"%x",value) 转换为十六进制数值。
sprintf(str,"%o",value) 转换为八进制数值。
1. char *
strcpy ( char * destination, const char * source );
最常用的函数,但是却不安全,原因在于,一是要destination有足够的空间,二是要保证source和destination指向的空间没有overlap。
2. int sprintf
( char * str, const char * format, ... );
也许要问,这个怎么用于字符串拷贝呢?可以这么用 sprintf(dest, "%s", src); 但是要调用者保证dest有足够的内存存放src。
3. char *
strncpy ( char * destination, const char * source, size_t num );
比起strcpy,多了个长度的控制。从source拷贝num个字符到destination。如果source里不够num字符怎么办呢?会补充0。
一个典型的用法是:
char buf[MAX];
strncpy(buf, src, MAX-1);
这段代码的本意是,一个长为MAX的buf,最多也就放MAX-1个字符,最后一个位置放‘\0'。因此最多能从src里拷贝MAX-1个字符,如果src里没这么多,剩余的填充0就是了。
但是这样做就安全了么?不是,如果src刚好MAX-1个字符。注意到strncpy只复制了MAX-1个字符,最后一个位置未知,有潜在的隐患。下段代码可以诠释:
#define MAX 4
char buf[MAX];
char* src="123";
memset(buf, 'x', MAX);
// solution 1. memset(buf, 0, MAX);
strncpy(buf, src, MAX-1);
// solution 2. buf[MAX-1] = '\0';
printf("%s\n", buf);
有两个办法可以解决:1. 调用strncpy之前memset为0,有点浪费。2. 在strncpy之后对最后一个字符赋值为0。
都可以,但不够优雅。
4. int snprintf( char *buffer, int buff_size, const char *format, ... );
用作字符串拷贝的用法:
char buf[MAX];
snprintf(buf, sizeof(buf), "%s", src);
即安全,又简洁。
你可能会关心:如果src的长度大于dest(buf)呢?这个是另外一个问题,这里需要的是安全的字符串拷贝,在C语言里,如果一个字符串指针指向的内存没有结尾字符'\0',是非常危险的。
snprintf会把buf的最后一个位置保留为'\0'。
关于返回值:如果当前buf够用,返回实际写入的字符数;如果不够用,返回将要写入的字符数。换句话说,返回值就是传入的字符数目。
假设当前的buf[4].
待写入 实际写入 返回值
12 12 2 够用
123 123 3 够用
1234 123 4 不够用
12345 123 5 不够用
sprintf/snprintf的另外一个用法:
itoa不是ANSI C或C++的一部分,可以变相的用sprintf来代替:
sprintf(str,"%d",value) 转换为十进制数值。
sprintf(str,"%x",value) 转换为十六进制数值。
sprintf(str,"%o",value) 转换为八进制数值。
相关文章推荐
- strcpy/strncpy/sprintf/_snprintf/snprintf的区别
- sprintf、snprintf、strcpy、strncpy
- c++字符串拷贝几个方法浅析sprintf,strcpy及memcpy
- 防御编程之字符串拷贝 memcpy strcpy strncpy lstrcpy lstrncpy wstrcpy
- (转)防御编程之字符串拷贝 memcpy strcpy strncpy lstrcpy lstrncpy wstrcpy
- strcpy strncpy (拷贝字符串)
- strcpy, strncpy, strcat, strncat, sprintf, snprintf等常用函数
- linux中strcpy strncpy memcpy sprintf snprintf区别总结
- 字符串拷贝函数strcpy, strcat, sprintf, strncpy, strncat和snprintf的区别
- 尽量使用strncpy,snprintf,少用strcpy,sprintf
- 完成字符串拷贝(sprintf、strcpy 及 memcpy 函数)函数之间的区别
- snprintf比sprintf好,那么strncpy就比strcpy好?!
- 字符串 函数sprintf、strcpy 、strncpy及 memcpy , strftime,strcat
- 具有自动截断功能的函数:对比:strcpy、strncpy、sprintf、snprintf在写入的数据大于缓冲区的情况下如何处理
- 打印字符串的安全函数snprintf
- 【字符串拷贝函数】memcpy strcpy strncpy lstrcpy lstrncpy wstrcpy的区别
- strcat,strncat,strcpy,strncpy,snprintf,vsnprintf
- Strlcpy和strlcat——一致的、安全的字符串拷贝和串接函数
- C语言中的几个字符串处理函数: strcat, strncat, strcpy, strncpy, strlen
- C语言snprintf()函数:将格式化的数据写入字符串—sprintf()