在使用许多标准C库函数的一些Microsoft安全版本时,我注意到其中一些函数似乎能够在编译时确定传入缓冲区是静态还是动态分配的。如果输入缓冲区是静态分配的,则函数可以自动地确定它的大小,但如果是动态的,则必须将该大小作为另一个参数给出。
例如,这段代码在静态分配缓冲区时起作用:
char buffer[1024];
sprintf_s(buffer, "Hello World\n");
printf_s(buffer);
然而,这不是:
char *buffer = new char[1024];
sprintf_s(buffer, "Hello World\n");
printf_s(buffer);
我已经尝试过查看这些函数的定义,但代码主要是预处理程序定义,这些定义非常令人困惑,无法尝试遵循。
所以我的问题是:这是如何确定的,这是一个标准的C / C ++语言功能还是某种特定于Microsoft的功能?
这些函数中的一些似乎没有意义,例如printf_s()与printf()具有完全相同的函数定义,那为什么它们甚至会有这个呢?
如果有人能够对此有所启发,我会很感激。
答案 0 :(得分:5)
如果你看一下sprintf_s, _sprintf_s_l, swprintf_s, _swprintf_s_l的参考文档,你会发现以下声明:
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
使用重载时,编译器可以在传递静态大小的数组时确定数组大小。这是标准的C ++,这里没有Microsoft特有的(除了重载和命名)。
答案 1 :(得分:0)
有一个名为_countof的Microsoft宏,它将提供静态数组的大小。这可能用于执行与printf_s相关的安全功能。根据{{3}},还有一种C ++ 11非宏方式(实现静态数组的大小)。
答案 2 :(得分:0)
这些函数似乎能够在编译时确定传入的缓冲区是静态还是动态分配的
他们不是。
这是类型系统的简单用例;在一种情况下,你传递一个数组(并且,请记住,数组类型包括维度!)。在另一方面,你传递一个指针。
对于所有编译器都知道,指针可以是使用恒星辐射分配的一块奶酪。