Date: Sun, 05 Jun 2011 20:42:45 +0000 From: "Poul-Henning Kamp" <phk@freebsd.org> To: Ben Laurie <ben@links.org> Cc: hackers@freebsd.org Subject: Re: int64_t and printf Message-ID: <12271.1307306565@critter.freebsd.dk> In-Reply-To: Your message of "Sun, 05 Jun 2011 21:17:45 %2B0100." <4DEBE469.5060305@links.org>
next in thread | previous in thread | raw e-mail | index | archive | help
In message <4DEBE469.5060305@links.org>, Ben Laurie writes: >On 05/06/2011 19:21, Poul-Henning Kamp wrote: >> In message <4DEBC741.1020200@links.org>, Ben Laurie writes: >> I have therefore resorted to printf'ing any typedefed integer type using >> "%jd" and an explicit cast to (intmax_t): >> >> printf("%-30s -> %jd -> %s\n", s, (intmax_t)t, buf); > >My objection to this approach is the lack of type-safety - t could be >anything and this would continue to work. > >Using PRId64 at least ensures that t is of an appropriate type. Uhm, no, it doesn't. At best it allows the compiler to make well chosen assumptions about what the printf(3) function does. Printf-format warnings are usually lost as soon as you go through stdarg/v*printf, because people don't know they should add __printflike() and other nonportable gunk to their prototypes. And they are totally lost if you use extended printf formatting of any kind, because there is no way to tell the compiler that "%Y takes a void *" This is basically why the work I did in <printf.h> is practically useless. But worse: PRId64 only works if you know your variable actually is 64bit. If you are trying to write code which works with typedefs on both 32 and 64 bit platforms you cannot know this. It's all nice and dandy that they made a magic "z" letter for size_t, but what about uid_t, gid_t, pid_t, off_t, ino_t, mode_t, nlink_t, fflags_t and so on ? You will therefore be forced to cast your argument to (int64_t) before you can use PRId64 safely on it. Now you have messed up the format string without loosing the cast and now your code will DTWT once somebody typedefs pid_t to int71_t. >Providing a better printf seems like an even smarter idea, e.g. > > printf("%-30s -> %I64d -> %s\n", s, t, buf); Same problem as above. There is no way to do this sanely, without involving the compiler. At the very least, the compiler would need to mangle the format string, so that you write: printf("%-30?d\n", sometype) and the compiler replaces the '?' with whatever is suitable for the width of the argument. Alternatively, and more useful, would be a type-safe or at least type-aware stdarg, so that prinf(3) could ask about the width and type of the next argument. Both would be wonderful additions to ISO-C but you can produce a college fresh-man from scratch starting now, before that happens. (See also Bjarnes approx. 1985 discussion of why C++ overloads << instead of providing printf(3)). -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk@FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?12271.1307306565>