Microsoft 的 C 库函数的 C++ 安全版本如何知道静态缓冲区的大小?

How do Microsoft's C++ safe versions of C library functions know the size of static buffers?

在使用许多标准 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() 具有完全相同的函数定义,那么为什么他们甚至有这个?

如果有人能对此有所启发,我将不胜感激。

有一个名为 _countof which will give the size of static arrays. This is probably being used in the implementation of the printf_s-related safe functions. According to this answer 的 Microsoft 宏,还有一个 C++11 非宏方法可以做到这一点(获取静态数组的大小)。

如果您查看 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 的内容(重载和命名除外)。


更多信息可在 Secure Template Overloads as well as Parameter Validation 下找到。

these functions seem capable of determining at compile time if a passed in buffer is allocated statically or dynamically

他们不是。

这是类型系统的一个简单用例;在一种情况下,您正在传递一个数组(并且,请记住,数组类型包括维度!)。另一方面,您正在传递一个指针。

据编译器所知,该指针可能指向一块使用恒星辐射分配的奶酪。