user-0 提问: 关于函数sprintf_s()用法的疑问

回复:
user: user-1
content: sprintf_s 后缀 s 是safe的缩写，代表这个函数是sprintf的安全版本。 改正一下  下面这个，不管能不能编译通过，都是错误的。  sprintf_s(filename,"%s %s %s %s",path1,path2,path3,path4);  "%s %s %s %s"，这个指针（常量字符串，字符串字面值），强制转换成size_t 整型数，path1被看作，格式化串。 居然能编译通过？？？？？，不过运行时就错得离谱了。 只能得到path1，因为path1里无格式符号 ，即无 %。  输出结果可能是这样的， "D:\Program\Tesseract-OCR\tesseract.exe";  这种用法， sprintf_s是不能保证安全的，地址的值至少Windows 上32Bits 是个很大的数字。 这样一来，就没有安全可言了。 size_t sizeOfBuffer,这个参数，是控制结果的。 保证sprintf_s 结果的串长，不超过sizeOfBuffer。

user: user-1
content: sprintf_s(filename,1024, "%s %s %s %s",path1,path2,path3,path4); 这是正确的。 下面这个，不管能不能编译通过，都是错误的。  sprintf_s(filename,1024, "%s %s %s %s",path1,path2,path3,path4);  "%s %s %s %s"，这个指针（常量字符串，字符串字面值），强制转换成size_t 整型数，path1被看作，格式化串。 居然能编译通过？？？？？，不过运行时就错得离谱了。 只能得到path1，因为path1里无格式符号 ，即无 %。  输出结果可能是这样的， "D:\Program\Tesseract-OCR\tesseract.exe";

user: user-2
content: 引用 21 楼 jiaoyun007 的回复:[quote=引用 18 楼 mujiok2003 的回复:] 有重载版本template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,    argument] ...  ); // C++ only 这位仁兄，你是从哪找到的？发个链接可好 [/quote] 这是链接

user: user-3
content: warning C4047: “函数”:“size_t”与“char [12]”的间接级别不同 warning C4024: “sprintf_s”: 形参和实参 2 的类型不同 VS2012只会warning不会error 我的结论是即使参数类型不同，假如两者可以强制转换，编译器只会警告不会报错。  楼主代码报错的原因其实跟sprintf_s一点关系也没，原因只有一个： error C2065: “new”: 未声明的标识符。 C语言里是没有new关键字的，你换用malloc就不报错了。以及，代码只能这么写，不能省略中间参数。 sprintf_s(filename,1024, "%s %s %s %s",path1,path2,path3,path4);

user: user-0
content: 引用 18 楼 mujiok2003 的回复:有重载版本template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,    argument] ...  ); // C++ only 这位仁兄，你是从哪找到的？发个链接可好

user: user-4
content: int sprintf_s(    char *buffer,    size_t sizeOfBuffer,    const char *format [,    argument] ...  ); template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,    argument] ...  ); // C++ only   MSDN给出了答案。

user: user-0
content: 引用 18 楼 mujiok2003 的回复:有重载版本template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,    argument] ...  ); // C++ only  这个答案靠谱！

user: user-2
content: 有重载版本template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,    argument] ...  ); // C++ only

user: user-5
content: Collapse AllExpand All      Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript   Visual Basic C# Visual C++ J# JScript Run-Time Library Reference  sprintf_s, _sprintf_s_l, swprintf_s, _swprintf_s_l  Example  See Also  Send Feedback     Write formatted data to a string. These are versions of sprintf, _sprintf_l, swprintf, _swprintf_l, __swprintf_l with security enhancements as described in Security Enhancements in the CRT.    int sprintf_s(    char *buffer,    size_t sizeOfBuffer,    const char *format [,       argument] ...  ); int _sprintf_s_l(    char *buffer,    size_t sizeOfBuffer,    const char *format,    locale_t locale [,       argument] ...  ); int swprintf_s(    wchar_t *buffer,    size_t sizeOfBuffer,    const wchar_t *format [,       argument]... ); int _swprintf_s_l(    wchar_t *buffer,    size_t sizeOfBuffer,    const wchar_t *format,    locale_t locale [,       argument]… ); template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,       argument] ...  ); // C++ only template <size_t size> int swprintf_s(    wchar_t (&buffer)[size],    const wchar_t *format [,       argument]... ); // C++ only    Parameters buffer Storage location for output  sizeOfBuffer Maximum number of characters to store.  format Format-control string  argument Optional arguments  locale The locale to use.  For more information, see Format Specifications.  Return Value The number of characters written, or –1 if an error occurred. If buffer or format is a null pointer, sprintf_s and swprintf_s return -1 and set errno to EINVAL.  sprintf_s returns the number of bytes stored in buffer, not counting the terminating null character. swprintf_s returns the number of wide characters stored in buffer, not counting the terminating null wide character.  Remarks The sprintf_s function formats and stores a series of characters and values in buffer. Each argument (if any) is converted and output according to the corresponding format specification in format. The format consists of ordinary characters and has the same form and function as the format argument for printf. A null character is appended after the last character written. If copying occurs between strings that overlap, the behavior is undefined.  One main difference between sprintf_s and sprintf is that sprintf_s checks the format string for valid formatting characters, whereas sprintf only checks if the format string or buffer are NULL pointers. If either check fails, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, the function returns -1 and sets errno to EINVAL.  The other main difference between sprintf_s and sprintf is that sprintf_s takes a length parameter specifying the size of the output buffer in characters. If the buffer is too small for the text being printed then the buffer is set to an empty string and the invalid parameter handler is invoked. Unlike snprintf, sprintf_s guarantees that the buffer will be null-terminated (unless the buffer size is zero).  swprintf_s is a wide-character version of sprintf_s; the pointer arguments to swprintf_s are wide-character strings. Detection of encoding errors in swprintf_s may differ from that in sprintf_s. The versions of these functions with the _l suffix are identical except that they use the locale parameter passed in instead of the current thread locale.  In C++, using these functions is simplified by template overloads; the overloads can infer buffer length automatically (eliminating the need to specify a size argument) and they can automatically replace older, non-secure functions with their newer, secure counterparts. For more information, see Secure Template Overloads.  There are versions of sprintf_s that offer additional control over what happens if the buffer is too small. For more information, see _snprintf_s, _snprintf_s_l, _snwprintf_s, _snwprintf_s_l.  TCHAR.H routine   _UNICODE & _MBCS not defined  _MBCS defined  _UNICODE defined   _stprintf_s  sprintf_s  sprintf_s  swprintf_s   _stprintf_s_l  _sprintf_s_l  _sprintf_s_l  _swprintf_s_l    Requirements Routine  Required header   sprintf_s, _sprintf_s_l  <stdio.h>   swprintf_s, _swprintf_s_l  <stdio.h> or <wchar.h>    For additional compatibility information, see Compatibility in the Introduction.  Example   Copy Code  // crt_sprintf_s.c // This program uses sprintf_s to format various // data and place them in the string named buffer. //  #include <stdio.h>  int main( void ) {    char  buffer[200], s[] = "computer", c = 'l';    int   i = 35, j;    float fp = 1.7320534f;     // Format and print various data:     j  = sprintf_s( buffer, 200,     "   String:    %s\n", s );    j += sprintf_s( buffer + j, 200 - j, "   Character: %c\n", c );    j += sprintf_s( buffer + j, 200 - j, "   Integer:   %d\n", i );    j += sprintf_s( buffer + j, 200 - j, "   Real:      %f\n", fp );     printf_s( "Output:\n%s\ncharacter count = %d\n", buffer, j ); }     Copy Code  Output:    String:    computer    Character: l    Integer:   35    Real:      1.732053  character count = 79     Copy Code  // crt_swprintf_s.c // wide character example // also demonstrates swprintf_s returning error code #include <stdio.h>  int main( void ) {    wchar_t buf[100];    int len = swprintf_s( buf, 100, L"%s", L"Hello world" );    printf( "wrote %d characters\n", len );    len = swprintf_s( buf, 100, L"%s", L"Hello\xffff world" );    // swprintf_s fails because string contains WEOF (\xffff)    printf( "wrote %d characters\n", len ); }     Copy Code  wrote 11 characters wrote -1 characters    .NET Framework Equivalent System::String::Format  See Also Concepts Stream I/O fprintf, _fprintf_l, fwprintf, _fwprintf_l printf, _printf_l, wprintf, _wprintf_l scanf, _scanf_l, wscanf, _wscanf_l sscanf, _sscanf_l, swscanf, _swscanf_l vprintf Functions Send feedback on this topic to Microsoft.

user: user-0
content: 纳闷了，代码这样写：  int _tmain(int argc, _TCHAR* argv[]) { 	char filename[1024];//预先分配缓冲区 	char path1[128] = "D:\\Program\\Tesseract-OCR\\tesseract.exe"; 	char path2[128] = "D:\\Program\\Tesseract-OCR\\"; 	char path3[128] = "D:\\Program\\Tesseract-OCR\\txt"; 	char path4[128] = "-l chi_sim"; 	sprintf_s(filename,1024, "%s %s %s %s",path1,path2,path3,path4); //无论这里是否有1024这个参数，都可以编译通过 	 	return 0; 	 }  在VS2010下测试，有疑问啊

user: user-0
content: 真的有点纳闷了，代码如下：      ... ...     char* filename = new char[1024]; //这样就会报出编译错误     char path1[128] = "D:\\Program\\Tesseract-OCR\\tesseract.exe";     char path2[128] = "D:\\Program\\Tesseract-OCR\\";     char path3[128] = "D:\\Program\\Tesseract-OCR\\txt";     char path4[128] = "-l chi_sim";     sprintf_s(filename,1024，"%s %s %s %s",path1,path2,path3,path4);     delete []filename;     return 0; ... ...  就可以，改成下面：  char filename[1024];//这个可以     char* filename = new char[1024]; //这样就会报出编译错误     char path1[128] = "D:\\Program\\Tesseract-OCR\\tesseract.exe";     char path2[128] = "D:\\Program\\Tesseract-OCR\\";     char path3[128] = "D:\\Program\\Tesseract-OCR\\txt";     char path4[128] = "-l chi_sim";     sprintf_s(filename,"%s %s %s %s",path1,path2,path3,path4);     delete []filename;

user: user-0
content: 在VS2010下试了下，代码如下：   #include "stdafx.h" #include "stdio.h"   int _tmain(int argc, _TCHAR* argv[]) { 	//char filename[1024];//这个可以 	char* filename = new char[1024]; //这样就会报出编译错误 	char path1[128] = "D:\\Program\\Tesseract-OCR\\tesseract.exe"; 	char path2[128] = "D:\\Program\\Tesseract-OCR\\"; 	char path3[128] = "D:\\Program\\Tesseract-OCR\\txt"; 	char path4[128] = "-l chi_sim"; 	sprintf_s(filename,"%s %s %s %s",path1,path2,path3,path4); 	delete []filename; 	return 0; }  使用 char* filename = new char[1024];  就会报出如下错误：  error C2664: 'int sprintf_s(char *,size_t,const char *,...)' : cannot convert parameter 2 from 'const char [12]' to 'size_t'

user: user-1
content: 2.1)应该是 格式里只包含一个简单格式 ,即 %s,%2d,这种，不包含  %*.*f ， %*d 这种一个格式多个数据的格式。 2.2)应该是 格式里包含若干个格式,或者包含 %*.*f 这种一个格式多个数据的格式。

user: user-1
content: 引用 8 楼 jiaoyun007 的回复:我是在VS2005下 ++  楼上给你答案了。 error：the second paramater can't covert from char[74] to size_t 错误，第二个参数，不能从 74元素的char类型数组,转换成size_t 类型 ---size_t 类型是标准库定义的数据类型，一般实现为无符号长整型unsigned long, 或者无符号整型unsigned int; VC8,VC9 可能是 unsigned long long 或者 unsigned __int64。//为了用于表示 64 Bits 文件长度。   int sprintf_s( char *buffer, size_t sizeOfBuffer,  //这个参数size_t 类型，你传递了一个74元素的char类型数组 const char *format [,//这个[,argument] 表示可选参数，实际函数原型，参数表里没有他                       //只有,... 四个符号 argument] ... );   使用方式 1) format 不包含任何格式 int ret = sprintf_s(     buffer,          //保存结果的字符串缓冲。       sizeOfBuffer,    //最长保留的字符数量，多余的截断。至多比 buffer的容量少一个，要放结束符。     format);         //格式串，可以没有任何格式，没有的话，后面不必有参数了。 sprintf_s(buffer,sizeOfBuffer, format);  2) format包含格式 2.1）格式里只包含一个格式 int ret = sprintf_s(buffer,sizeOfBuffer, format,a); sprintf_s(buffer,sizeOfBuffer, format,a); 2.2）格式里只包含一个格式 int ret = sprintf_s(buffer,sizeOfBuffer, format,a,b,c); sprintf_s(buffer,sizeOfBuffer, format,a,b,c);  你需要的是楼上那种用法，format 就是 "%s" 即： char msg[100]; char src[74]="You are Wellcome"; sprintf_s(msg,min(99,strlen(src)),"%s",src); 这种。

user: user-0
content: 引用 5 楼 xyzinfernity 的回复:  VS2012下测试没问题,楼主出的问题在其他方面吧，error：the second paramater can't covert from char[74] to size_t,说明你的sprintf_s第二个参数是char[74]类型的  我是在VS2005下

user: user-0
content: 引用 6 楼 lm_whales 的回复:函数调用时，有名名参数一个都不能缺少，一个一个对应匹配。 无名参数（。。。），根据需要，匹配，实参不能用省略号。  实际当然不是省略号了

user: user-1
content: 函数调用时，有名名参数一个都不能缺少，一个一个对应匹配。 无名参数（。。。），根据需要，匹配，实参不能用省略号。

user: user-3
content: VS2012下测试没问题,楼主出的问题在其他方面吧，error：the second paramater can't covert from char[74] to size_t,说明你的sprintf_s第二个参数是char[74]类型的

user: user-6
content: google 个例子看看

user: user-0
content: 下面用法也报同样的错，不知道为何：   void func2(char **pMsg) {     ......     sprintf_s(*pMsg, ...);      ...... }  void func1() {     char msg[100];      func2(&msg); }