snprintf 返回值陷阱 重新封装

简介: snprintf()函数用于将格式化的数据写入字符串,其原型为: int snprintf(char *str, int n, char * format [, argument, ...]);str为要写入的目标字符串;n为能写入的字符的最大数目,超过n会被截断,包括'\0'符,所以能最大写入的其实是n-1个字符;format为格式化字符串,使用方式与printf()函数相同;argument为变量,可为多个,取决于format,这里的使用方式与printf相同。

snprintf()函数用于将格式化的数据写入字符串,其原型为:

    int snprintf(char *str, int n, char * format [, argument, ...]);
  • str为要写入的目标字符串;
  • n为能写入的字符的最大数目,超过n会被截断,包括'\0'符,所以能最大写入的其实是n-1个字符;
  • format为格式化字符串,使用方式与printf()函数相同;
  • argument为变量,可为多个,取决于format,这里的使用方式与printf相同。
  • 成功则返回参数str 字符串长度(不包括“\0”),失败则返回-1,错误原因存于errno 中。

snprintf()可以认为是sprintf()的升级版,比sprintf()多了一个参数,可以控制要写入的字符串的长度,更加安全,不会造成str的溢出。

不过snprintf也不是尽善尽美的,也有陷阱,当要写入的argument的长度大于str的长度时,返回值不是str的长度,而是argument的长度

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int len;
    char str[5];
    len = snprintf(str, sizeof(str), "%s", "ABCDEFGH");
    printf("str:%s, len:%d.\n", str, len);

    return 0;
}

输出结果:

str:ABCD, len:8.

返回的长度是8而不是4,不注意的话,下边的使用可能有问题。所以,使用后,下边最好再判断一下len的长度是否超过了size。
其实可以自己封装一个my_snprintf的

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

int my_snprintf(char *dst, int size, char *fmt, ...)
{
    int len;
    va_list argp;
    va_start(argp, fmt);
    len = vsnprintf(dst, size, fmt, argp);
    len = len > size - 1 ? size - 1 : len;
    va_end(argp);
    
    return len;
}

int main(void)
{
    char str[8];
    int len;
    
    len = my_snprintf(str, sizeof(str), "A:%d:%s", 1, "ABCDEFGH");
    printf("str:%s, len:%d\n", str, len);

    return 0;
}

输出:

str:A:1:ABC, len:7
目录
相关文章
|
4月前
|
存储 编译器 C语言
【C/C++ 函数返回的奥秘】深入探究C/C++函数返回:编译器如何处理返回值
【C/C++ 函数返回的奥秘】深入探究C/C++函数返回:编译器如何处理返回值
490 3
|
1月前
|
存储
hyengine 寄存器问题之传递参数和接收返回值如何解决
hyengine 寄存器问题之传递参数和接收返回值如何解决
|
4月前
|
编译器 Linux C语言
C/C++ 常见函数调用约定(__stdcall,__cdecl,__fastcall等):介绍常见函数调用约定的基本概念、用途和作用
C/C++ 常见函数调用约定(__stdcall,__cdecl,__fastcall等):介绍常见函数调用约定的基本概念、用途和作用
65 0
|
4月前
|
编译器 C语言
C语言中的按值调用(Call by Value)技术详解
C语言中的按值调用(Call by Value)技术详解
51 0
|
4月前
|
存储 C语言
C语言函数的返回值
C语言函数的返回值
41 0
|
4月前
|
编译器 程序员 Linux
深入理解C语言中的return关键字与函数返回机制
深入理解C语言中的return关键字与函数返回机制
394 1
|
4月前
|
C语言
C语言 -- 如何传递数组参数
C语言 -- 如何传递数组参数
57 3
|
4月前
|
Unix Linux C语言
【C/C++ 跳转函数】setjmp 和 longjmp 函数的巧妙运用: C 语言错误处理实践
【C/C++ 跳转函数】setjmp 和 longjmp 函数的巧妙运用: C 语言错误处理实践
76 0
|
4月前
|
编译器 C语言
<C语言错误处理> strerror和perror函数以及断言处理方式
<C语言错误处理> strerror和perror函数以及断言处理方式
|
4月前
|
编译器 C语言
C语言中函数宏的三种封装方式详解
C语言中函数宏的三种封装方式详解
79 0