I assume that your interest is shown primarily in terms of performance, since solutions such as vector, string, wstring, etc., as a rule, will work even for interacting with C APIs. I recommend learning how to use them and how to use them effectively. If you really need it, you can even write your own memory allocator to make them super fast. If you are sure that they are not what you need, you still have no excuse for not writing a simple wrapper to handle these string buffers using RAII for dynamic cases.
With this in mind:
Passing a buffer as a buffer [0] is a better programming style than a buffer transition? (I prefer the buffer [0].)
Not. I would find this style a little less useful (admittedly subjective here) since you cannot use it to pass a null buffer, and so you have to make exceptions in your style to pass pointers to arrays that may be empty . However, this is necessary if you are passing data from std :: vector to the C API, waiting for a pointer.
Is there a maximum size considered safe for dedicated stack buffers?
It depends on your platform and compiler settings. A simple rule of thumb: if you doubt that your code will overflow the stack, write it in the wrong way.
Is the static buffer (static charbuffer [N];) faster? Are there any other arguments for or against him?
Yes, there is a big argument against this, and this means that your function ceases to be repeated. If your application becomes multithreaded, these functions will not be thread safe. Even in a single-threaded application, sharing the same buffer while recursively calling these functions can lead to problems.
How about using a static buffer char * = new char [N]; and never delete the buffer? (Reusing the same call buffer.)
We still have the same problems with reconnecting.
I understand that heap allocation should be used when (1) deals with large buffers or (2) the maximum size buffer is unknown at compile time. Are there other factors that play into the decision about stack / heap allocation?
Stacking destroys objects on the stack. This is especially important for exception safety. Thus, even if you allocate memory on the heap inside a function, you should usually manage the object on the stack (for example: smart pointer) .///@ see section RAII.
If you prefer sprintf_s, memcpy_s, ... options? (Visual Studio tried to convince me of this for a long time, but I want a second opinion: p)
MS was right about these functions, which are safer alternatives, since they have no problems with buffer overflows, but if you write such code as it is (without writing options for other platforms), your code will marry Microsoft. since it will not be portable.
When using static buffers, you can use return type const char *. Is this a (generally) good or bad idea? (I realize that the caller to make his own copy to avoid the next call will change the previous return value.)
I would say in almost every case, you want to use const char * for return types for a function that returns a pointer to a character buffer. For a function returning a mutable char *, it is usually confusing and problematic. Or it returns an address to global / static data that it should not use first (see Re-inclusion above), local class data (if it is a method), in which case its return destroys the class’s ability to maintain invariants, allowing clients to intervene into this, but they like it (for example: the stored string should always be valid) or return the memory indicated by the pointer passed to the function (the only case where it could reasonably be said that mutable char * should be returned).