ISO: WG21/N0499 ANSI: 94-0112 Author: John Max Skaller Date: May 1994 Reply to: maxtal@suphys.physics.su.oz.au "TYPE SAFE PRINTF" ------------------ Although we have iostreams, may programmers continue to use the C streams. They are after all, part of the C++ Standard Library. I have found its very common using the formatted IO functions to get the types wrong: long ch; printf("%d", ch); // wrong in some cases, its not even so easy to get it right portably: size_t n; printf("%d", n); // implementation dependency! Well, C programmers have "lint", but we've got real compilers! Proposal -------- In calls to the Standard Library functions printf(), sprintf(), fprintf(), vsprintf(), scanf(), sscanf(), fscanf() and vscanf() and matching wide character versions of these functions, if the format control argument is given as a C style null terminated string literal, then the arguments will be type checked and a diagnostic issued if insufficient arguments are given, or arguments of a type which would lead to undefined behaviour are given. No diagnostic is required otherwise. Whether and how vendor extensions to the format codes are checked is implementation defined. Example ------- const char * fmt = "%d"; long l; printf(fmt, l); // undiganosed error printf("%d",l); // ill-formed, diagnostic required printf("%d", Compatibility: -------------- NO change to the language is intended. This proposal simply requires a diagnostic for easily detectable errors, where previously no diagnostic was required. Question: Why should an error be diagnosed if the function is not actually called? Answer: Thats normal behaviour in other cases where types are checked. Question: Why should implementors be required to go to the extra trouble, especially for a C feature? Answer: There is some work involved for implementors, but not much compared to the hours lost by programmers writing bad function calls. This error is one of the _most_ common made by myself and others on my programming team. Answer 2: Often, we dont even know which format codes to use. Programmers typically rely on compilers, and not reference books or Standards to answer questions about what is OK and what isnt. Question: Why not just make it a quality of implementation issue? Answer: Because very few compilers today actually perform this check, and they have had plenty of time to implement it. Experience shows many vendors will not provide functionality not required by their target environment or the Standard. Requiring a diagnostic allows one to examine code that is accepted by a conforming compiler and tell immediately that most calls to this class of function cannot be causing a problem. Adding such safety guarrantees to a language enhances the ability to diagnose faults. Question: Why only string literals? Answer: Because it makes sense for the compiler, and user, to check what is literally visible, and the case of a general expression is not statically checkable. In many applications, especially where printf() is suitable (such as for debugging), the format controls wil be literals. Question: But we dont want to promote use of these functions! We have iostreams. Why should we do this? Answer: a) A lot of C programmers upgrading to C++ will write using familiar functions and idioms. b) If we havent the courage to deprecate these functions, we should make them as safe as possible. c) C++ has a philosophy of supporting multiple paradigms. d) The C functions are Standardised, well understood, and used frequently. Many people like them, and some even prefer them to iostreams (including me). I believe we have no right to prevent programmers making this decision, and we should support this usage by diagnosing errors when possible. e) There is a large body of existing C code that may be ported to C++ compilers. Often implementation assumptions such as that a size_t is the same size as an int change, and the printf family may silently fail in these cases unless a diagnostic is mandated.