Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!sq!msb From: msb@sq.UUCP Newsgroups: comp.lang.c Subject: Re: printf and variable length string format (asterisk) Message-ID: <1987Nov27.024339.12253@sq.uucp> Date: Fri, 27-Nov-87 02:43:39 EST Article-I.D.: sq.1987Nov27.024339.12253 Posted: Fri Nov 27 02:43:39 1987 Date-Received: Sun, 29-Nov-87 15:24:26 EST References: <692@zycad.UUCP> Reply-To: msb@sq.UUCP (Mark Brader) Organization: SoftQuad Inc., Toronto Lines: 56 Checksum: 15011 There have been several followups to this one, but they have all missed a significant point. > I want to print out a string whose length I will not know ahead, and which > is not null terminated. > [I tried] ... printf("%*s\n", i, a); Most people pointed out that he meant "%.*s". However, according to the ANSI Draft Standard, that usage is NOT portable. The reason is that the Draft requires that the argument a "shall be a pointer to a string". And a string is defined as "an array of characters *terminated by a null character*" [my emphasis]. This means that an implementation may, on encountering the above, cheerfully go on reading characters past the end of a until it runs off the end of memory (or the segment of memory) and aborts... no matter what the value of i is. Fully portable ways to do this would be: [1] { int j; for (j = 0; j < i; ++j) putchar (a[j]); } putchar ('\n'); [2] { char *tmp = malloc (j+1); if (!tmp) abort(); strncpy (tmp, a, j); tmp[j] = 0; printf ("%s\n", tmp); free (tmp); } If you know a maximum size for a, you can avoid the malloc(). If a is known not to be const, there is also: [3] if (j) { char last = a[j-1]; a[j-1] = '\0'; printf ("%s%c", a, last); a[j-1] = last; } putchar ('\n'); It seems to me that both [1] and [2] are likely to be significantly slower than the "%.*s" method, which I expect will work on most or all existing implementations; and [3] is ugly and not always usable. I can't think of another reasonable approach, anyway. (You can't use fwrite(), for instance, because the Draft allows an implementation to distinguish text streams from binary streams.) Doug Gwyn pointed out the "string" requirement to me when I asked him by email about the acceptability of printf ("%.1s", &char_variable) to print a char unless it was a null. I agreed that this was a minor convenience at best. But thinking about the above example, and what you'd have to do, does make me wonder whether the Committee really considered this point before deciding to restrict all forms of %s to "strings". They might have decided that C was so strongly oriented to null-terminated strings that anyone who wants to use data structures like a is doing so at their own risk; or it might just have slipped by. You there, Doug? Mark Brader, SoftQuad Inc., Toronto "Suspicion breeds confidence." utzoo!sq!msb, msb@sq.com -- BRAZIL