BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsla_printf

Macros

#define BSLA_PRINTF(fmt, arg)
 

Detailed Description

Outline

Purpose

Provide a macro to indicate printf-style arguments.

Macros

See also
bsla_annotations

Description

This component provides a preprocessor macro that allows the designation of a given function argument as a printf-style format string, and arguments starting at a certain index in the argument list to be formatted according to that string.

Macro Reference

BSLA_PRINTF(FMTIDX, STARTIDX): This annotation instructs the compiler to perform additional compile-time checks on so-annotated functions that take printf-style arguments, which should be type-checked against a format string.

BSLA_PRINTF_IS_ACTIVE: The macro BSLA_PRINTF_IS_ACTIVE is defined if BSLA_PRINTF expands to something with the desired effect; otherwise BSLA_PRINTF_IS_ACTIVE is not defined and BSLA_PRINTF expands to nothing.

Usage

This section illustrates intended use of this component.

Example 1: printf-Like Function That Returns a bsl::string by Value

First, we define a function, strPrintf, that takes a variable number of arguments. The second argument is the format string, and we annotate it with BSLA_PRINTF:

std::string strPrintf(size_t *numChars, const char *format, ...)
BSLA_PRINTF(2, 3);
std::string strPrintf(size_t *numChars, const char *format, ...)
// Do a 'sprintf'-style write to a 'std::string' and return the string
// by value. Ensure that the write can't overflow unless memory or
// address space is exhausted. The specified '*numChars' is the number
// of characters written, the specified 'format' is the 'printf'-style
// format string, and the specified '...' is the variable-length list
// of arguments to be formatted.
{
std::string ret = " ";
va_list ap;
va_start(ap, format);
// 'vsnprintf' returns the number of characters that WOULD have been
// written (not including the terminating '\0') had the buffer been
// long enough.
*numChars = ::vsnprintf(&ret[0], 1, format, ap);
va_end(ap);
ret.resize(*numChars + 1);
va_start(ap, format);
*numChars = ::vsnprintf(&ret[0], *numChars + 1, format, ap);
va_end(ap);
BSLS_ASSERT(::strlen(ret.c_str()) == *numChars);
ret.resize(*numChars);
return ret;
}
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
Definition bdldfp_decimal.h:5188

Then, in main, we call the function correctly a couple of times:

size_t len;
std::string s;
s = strPrintf(&len, "%s %s %s %g\n", "woof", "meow", "arf", 23.5);
assert("woof meow arf 23.5\n" == s);
assert(19 == len);
assert(len == s.length());
s = strPrintf(&len, "%s %s %s %s %s %s %s %s %s\n",
"The", "rain", "in", "Spain", "falls", "mainly",
"in", "the", "plain");
assert("The rain in Spain falls mainly in the plain\n" == s);
assert(44 == len);
assert(len == s.length());

Now, we call it with too many arguments and of the wrong type:

s = strPrintf(&len, "%c %f %g", "arf", 27, 32, 65, 27);

Finally, we observe the compiler warnings with clang:

.../bsla_printf.t.cpp:328:41: warning: format specifies type 'int' but the
argument has type 'const char *' [-Wformat]
s = strPrintf(&len, "%c %f %g", "arf", 27, 32, 65, 27);
~~ ^~~~~
%s
.../bsla_printf.t.cpp:328:48: warning: format specifies type 'double' but
the argument has type 'int' [-Wformat]
s = strPrintf(&len, "%c %f %g", "arf", 27, 32, 65, 27);
~~ ^~
%d
.../bsla_printf.t.cpp:328:52: warning: format specifies type 'double' but
the argument has type 'int' [-Wformat]
s = strPrintf(&len, "%c %f %g", "arf", 27, 32, 65, 27);
~~ ^~
%d
.../bsla_printf.t.cpp:328:56: warning: data argument not used by format
string [-Wformat-extra-args]
s = strPrintf(&len, "%c %f %g", "arf", 27, 32, 65, 27);
~~~~~~~~~~ ^

Macro Definition Documentation

◆ BSLA_PRINTF

#define BSLA_PRINTF (   fmt,
  arg 
)