This is the code that **Toby Speight** suggested in his answer:

```c
/*
 * int	sbprintf(char buff[restrict], int *restrict written,
 *								const char *restrict format, ...);
 */
#define sbprintf(buff, written, format, ...)	(						\
{																		\
		int		len_;													\
																		\
		alx_static_assert_array(buff);									\
																		\
		len_	= snprintf((buff), sizeof(buff), format, ##__VA_ARGS__);\
		if (written != NULL)											\
				*written = len_;										\
		len_ >= (int)sizeof(buff);										\
}																		\
)
```

_________________________________________________

I have tested it and works as expected:

 - If `written` is `NULL` it doesn't write into it.
 - The return value is `true` when the string is truncated and `false` otherwise.
 - It doesn't compile if `buff` is not an array.
 - It accepts a variable number of arguments after `format`, including no arguments.

The comment above the macro is the prototype that a user should see, to better understand the usage, although a real function with that prototype wouldn't work because of the array decaying to a pointer.

____________________________________

Comments about the style:

I tried to follow the Linux Kernel Coding Style, but there have been exceptions:

`if (written != NULL)` is used instead of `if (written)` to avoid the compiler complaining:

```
main.c:22:23: error: the address of ‘w1’ will always evaluate as ‘true’ [-Werror=address]
  if (alx_sbprintf(b1, &w1, test))
                       ^
.../libalx/base/stdio/sbprintf.h:36:6: note: in definition of macro ‘alx_sbprintf’
  if (written)       \
      ^~~~~~~
```

_____________

**EDIT:**

Given that `snprintf` sets `errno` (at least in [POSIX][1]), it would be good to set `errno` to `ENOMEM` on truncation.

__________________________________________


**EDIT:**

This version includes the improvements suggested by **Toby Speight** and  **chux**, as well as setting `errno` on error.  First I added code to the macro, but it proved to have [some problems][2] (at least it didn't compile, so no dangerous bugs).  Now it's an `extern` function enclosed in a simple macro.

Now the code relies less on GCC extensions.

Properties:

 - If `written` is `NULL` it doesn't write into it.
 - It doesn't compile if `buff` is not an array.
 - It accepts a variable number of arguments after `format`, including no arguments.
 - Sets `errno` on any error.
 - If there's a `snprintf` internal error, the error code is negative (`-errno`), and `written` is also negative.
 - If the string is truncated, the error code is positive (`ENOMEM`).
 - If the error code is negative, the string should not be trusted;  if it's positive, it's been truncated, but it's a valid string.

Code:

`sbprintf.h`:
```c
#ifndef ALX_STDIO_PRINTF_SBPRINTF_H
#define ALX_STDIO_PRINTF_SBPRINTF_H


#include "libalx/base/assert/assert.h"
#include "libalx/base/stdio/printf/swnprintf.h"


/*
 * int	sbprintf(char buff[restrict], ptrdiff_t *restrict written,
 *				const char *restrict format, ...);
 */
#define sbprintf(buff, written, fmt, ...)	(							\
{																		\
																		\
		alx_static_assert_array(buff);									\
		swnprintf(buff, written, sizeof(buff), fmt, ##__VA_ARGS__);		\
}																		\
)


#endif		/* libalx/base/stdio/printf/sbprintf.h */
```


`swnprintf.h`:
```c
#ifndef ALX_STDIO_PRINTF_SWNPRINTF_H
#define ALX_STDIO_PRINTF_SWNPRINTF_H


#include <stddef.h>


int		swnprintf(char str[restrict], ptrdiff_t *restrict written, ptrdiff_t nmemb,
						const char *restrict format, ...);


#endif		/* libalx/base/stdio/printf/swnprintf.h */
```

`swnprintf.c`:
```c
#include "libalx/base/stdio/printf/swnprintf.h"

#include <errno.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>


int		swnprintf(char str[restrict], ptrdiff_t *restrict written, ptrdiff_t nmemb,
						const char *restrict format, ...)
{
		va_list	ap;
		int		len;

		if (nmemb < 0)
				goto neg;

		va_start(ap, format);
		len		= vsnprintf(str, nmemb, format, ap);
		va_end(ap);

		if (written != NULL)
				*written = len;

		if (len < 0)
				goto err;
		if (len >= nmemb)
				goto trunc;

		return	0;
trunc:
		if (written)
				*written = nmemb - 1;
		errno	= ENOMEM;
		return	ENOMEM;
neg:
		errno	= EOVERFLOW;
err:
		if (written)
				*written = 0;
		return	-errno;
}
```

**Edit:**

Modified to use `ptrdiff_t`: it allows to detect invalid (negative) sizes, instead of using their unsigned value.  Also removes a cast.

Modified to set `written` to 0 on error when the string is unreliable.



  [1]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html
  [2]: https://stackoverflow.com/q/56825271/6872717