Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

printf

1 view
Skip to first unread message

Jrdman

unread,
Sep 2, 2008, 7:43:37 PM9/2/08
to
someone has an idea on how the printf function is programmed ?

Ian Collins

unread,
Sep 2, 2008, 7:49:04 PM9/2/08
to
Jrdman wrote:
> someone has an idea on how the printf function is programmed ?

One would guess those who have implemented it!

Find the source for an implementation (there are many published) and
have a look.

--
Ian Collins.

Martin Ambuhl

unread,
Sep 2, 2008, 8:42:47 PM9/2/08
to
Jrdman wrote:
> someone has an idea on how the printf function is programmed ?

Yes.
If you want to look at one method of implementation (at least for the
features in C90), check P.J. Plauger's _The Standard C Library_
(prentice Hall, 1992). An implementation of the functions declared in
<stdio.h> is all of chapter 12, pp. 225-332. I'm not sure what short
answer you expect when Plauger takes 106 pages for this.

Pilcrow

unread,
Sep 3, 2008, 12:44:00 AM9/3/08
to

Thanks for the reference.

raashid bhatt

unread,
Sep 3, 2008, 1:04:18 AM9/3/08
to
On Sep 2, 7:43 pm, Jrdman <ahmed.bo...@gmail.com> wrote:
> someone has an idea on how the printf function is programmed ?

unser windows itz a function call in msvcrt.dll which in turn calls
kerne32.dll GetStdouthandle(); and after getting the handle it calls
WriteFile() function of kernel32.dl

Richard Heathfield

unread,
Sep 3, 2008, 2:15:59 AM9/3/08
to
raashid bhatt said:

> On Sep 2, 7:43 pm, Jrdman <ahmed.bo...@gmail.com> wrote:
>> someone has an idea on how the printf function is programmed ?
>
> unser windows itz a function call

It's a function call in *any* environment. And the rest of your answer is
unnecessarily platform-specific - the printf function can be written
portably.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Ron Ford

unread,
Sep 3, 2008, 3:10:38 AM9/3/08
to
On Wed, 03 Sep 2008 06:15:59 +0000, Richard Heathfield posted:

> raashid bhatt said:
>
>> On Sep 2, 7:43 pm, Jrdman <ahmed.bo...@gmail.com> wrote:
>>> someone has an idea on how the printf function is programmed ?
>>
>> unser windows itz a function call
>
> It's a function call in *any* environment. And the rest of your answer is
> unnecessarily platform-specific - the printf function can be written
> portably.

sprintf too?

Is sprintf variadic?
--
War will never cease until babies begin to come into the world with larger
cerebrums and smaller adrenal glands. 2
H. L. Mencken

Richard Heathfield

unread,
Sep 3, 2008, 3:16:54 AM9/3/08
to
Ron Ford said:

> On Wed, 03 Sep 2008 06:15:59 +0000, Richard Heathfield posted:
>
>> raashid bhatt said:
>>
>>> On Sep 2, 7:43 pm, Jrdman <ahmed.bo...@gmail.com> wrote:
>>>> someone has an idea on how the printf function is programmed ?
>>>
>>> unser windows itz a function call
>>
>> It's a function call in *any* environment. And the rest of your answer
>> is unnecessarily platform-specific - the printf function can be written
>> portably.
>
> sprintf too?

Yes.

> Is sprintf variadic?

Yes.

Ron Ford

unread,
Sep 3, 2008, 3:33:02 AM9/3/08
to
On Wed, 03 Sep 2008 07:16:54 +0000, Richard Heathfield posted:

> Ron Ford said:
>
>> On Wed, 03 Sep 2008 06:15:59 +0000, Richard Heathfield posted:
>>
>>> raashid bhatt said:
>>>
>>>> On Sep 2, 7:43 pm, Jrdman <ahmed.bo...@gmail.com> wrote:
>>>>> someone has an idea on how the printf function is programmed ?
>>>>
>>>> unser windows itz a function call
>>>
>>> It's a function call in *any* environment. And the rest of your answer
>>> is unnecessarily platform-specific - the printf function can be written
>>> portably.
>>
>> sprintf too?
>
> Yes.

I see the syntax here in §7.2.

What I think a person might call this is an internal write. In fortran, we
go so far as to speak of "internal files," when what we really mean is the
character variable that we write to. I/O need not apply.

I'd be curious to see a useful snippet.
>
>> Is sprintf variadic?
>
> Yes.

This disqualifies it from fortran interop.
--
When a new source of taxation is found it never means, in practice, that
the old source is abandoned. It merely means that the politicians have two
ways of milking the taxpayer where they had one before. 8
H. L. Mencken

Malcolm McLean

unread,
Sep 3, 2008, 4:05:34 PM9/3/08
to

"Ron Ford" <r...@example.invalid> wrote in message
>
[sprintf ]

> I'd be curious to see a useful snippet.
>>
>
sprintf() can be written portably. printf() cannot, though it can be written
on top of putchar(), which has to be platform-specific.

An example use would be in BasicDraw. Microsoft have provided a function for
setting the window title which takes, reasonably enough, a char *. Since I
want the name of the program, the version, the name of the file it is
editing, and an asterisk to represent file dirty, I can write

sprintf(buff, "BasicDraw v%g [%s]%c", version, filename, dirty ? '*' : ' ');
setwindowtitle(win, buff);

without sprintf it would be awkward to build the title, or Microsoft would
have to complicate their title-setting function to accept variable
arguments.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

vipp...@gmail.com

unread,
Sep 3, 2008, 9:10:46 PM9/3/08
to
On Sep 3, 11:05 pm, "Malcolm McLean" <regniz...@btinternet.com> wrote:
> "Ron Ford" <r...@example.invalid> wrote in message
>
> [sprintf ]
> > I'd be curious to see a useful snippet.
>
> sprintf() can be written portably. printf() cannot, though it can be written
> on top of putchar(), which has to be platform-specific.

printf can also be written portably. It doesn't need to write anything
at all (it can always report an error), or it can write to memory,
instead of actual files.
Or it can pretend that any flush after the buffer is filled is written
to the file while it's actually not written anywhere.

P.S. Please don't reply to ron ford, he is a troll.

<snip>

Kenny McCormack

unread,
Sep 3, 2008, 9:54:20 PM9/3/08
to
In article <99670240-bc87-4643...@r35g2000prm.googlegroups.com>,
<vipp...@gmail.com> sucked CLC reg c*ck while writing:
...

>printf can also be written portably. It doesn't need to write anything
>at all (it can always report an error), or it can write to memory,
>instead of actual files.
>Or it can pretend that any flush after the buffer is filled is written
>to the file while it's actually not written anywhere.

Um, yeah...

>P.S. Please don't reply to ron ford, he is a troll.

With the crap you just wrote, now who exactly is a troll?

Keith Thompson

unread,
Sep 3, 2008, 10:27:00 PM9/3/08
to
vipp...@gmail.com writes:
> On Sep 3, 11:05 pm, "Malcolm McLean" <regniz...@btinternet.com> wrote:
[...]

>> sprintf() can be written portably. printf() cannot, though it can be written
>> on top of putchar(), which has to be platform-specific.
>
> printf can also be written portably. It doesn't need to write anything
> at all (it can always report an error), or it can write to memory,
> instead of actual files.
> Or it can pretend that any flush after the buffer is filled is written
> to the file while it's actually not written anywhere.
[...]

If it doesn't write anything at all, or writes to memory rather than
to a file, or pretends to write to a file while failing to do so, then
it's not an implementation of printf.

But the bulk of the processing done by printf *can* be done portably.
In fact, printf is typically a simple wrapper around fprintf.

And there's nothing non-portable about performing output by calling
putchar.

If you look at all the functions declared in <stdio.h> that perform
output, *at least one* of them has to be implemented non-portably --
and typically, I suspect, more than one of them will be.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

vipp...@gmail.com

unread,
Sep 3, 2008, 11:02:04 PM9/3/08
to
On Sep 4, 5:27 am, Keith Thompson <ks...@mib.org> wrote:

> vipps...@gmail.com writes:
> > On Sep 3, 11:05 pm, "Malcolm McLean" <regniz...@btinternet.com> wrote:
> [...]
> >> sprintf() can be written portably. printf() cannot, though it can be written
> >> on top of putchar(), which has to be platform-specific.
>
> > printf can also be written portably. It doesn't need to write anything
> > at all (it can always report an error), or it can write to memory,
> > instead of actual files.
> > Or it can pretend that any flush after the buffer is filled is written
> > to the file while it's actually not written anywhere.
>
> [...]
>
> If it doesn't write anything at all, or writes to memory rather than
> to a file, or pretends to write to a file while failing to do so, then
> it's not an implementation of printf.

That sounds wrong to me.
If it doesn't write anything at all, it has to return a value less
than zero, and it will be conforming.
This, for example, is a valid implementation of printf:

int printf(const char *format, ...) { __set_errno(); return -1; }

Also, 7.19.2 Streams p1 seems to be quite vague about where input
comes from or where output goes to.

> Input and output, whether to or from physical devices such as terminals and tape drives,
> or whether to or from files supported on structured storage devices, are mapped into
> logical data streams, whose properties are more uniform than their various inputs and
> outputs. Two forms of mapping are supported, for text streams and for binary
> streams.

To me it seems that a file can be a region of memory. It would make no
difference to the programmer.

> But the bulk of the processing done by printf *can* be done portably.
> In fact, printf is typically a simple wrapper around fprintf.
>
> And there's nothing non-portable about performing output by calling
> putchar.

Yes I agree. There are also other ways to write printf portably that I
did not mention in my post.

> If you look at all the functions declared in <stdio.h> that perform
> output, *at least one* of them has to be implemented non-portably --
> and typically, I suspect, more than one of them will be.

I disagree. Assuming that "at least one" function is putc and getc:

int putc(int c, FILE *stream) { __set_errno(); return EOF; }
int getc(int c, FILE *stream) { __set_errno(); return EOF; }

Then all the functions in stdio are portable.


Even other functions like malloc can be written portably; I can
imagine the implementation having a __malloc_array[somesize]; in some
struct with other information;

Assuming no previous allocations, malloc could do something like this:

if(n < somesize) { somesize -= n; __ptr = __malloc_array + n; return
__malloc_array; }

Of course, it would be more complicated than that, but it can be done.
If you still disagree I'm willing to try to write such implementation
for malloc/realloc/calloc/free.

Another way to write malloc portably would be

void *malloc(size_t n) { __set_errno(); return NULL; }

Nick Keighley

unread,
Sep 4, 2008, 4:27:06 AM9/4/08
to
On 3 Sep, 08:33, Ron Ford <r...@example.invalid> wrote:
> On Wed, 03 Sep 2008 07:16:54 +0000, Richard Heathfield posted:
> > Ron Ford said:
> >> On Wed, 03 Sep 2008 06:15:59 +0000, Richard Heathfield posted:
> >>> raashid bhatt said:
> >>>> On Sep 2, 7:43 pm, Jrdman <ahmed.bo...@gmail.com> wrote:

> >>>>> someone has an idea on how the  printf  function is programmed ?
>
> >>>> unser windows itz a function call
>
> >>> It's a function call in *any* environment. And the rest of your answer
> >>> is unnecessarily platform-specific - the printf function can be written
> >>> portably.
>
> >> sprintf too?
>
> > Yes.
>
> I see the syntax here in §7.2.
>
> What I think a person might call this is an internal write.  In fortran, we
> go so far as to speak of "internal files," when what we really mean is the
> character variable that we write to.  I/O need not apply.

is english your first language? (I suspect "yes" as a non-native
speaker
wouldn't write such convoluted sentences) I often have difficulty
understanding you.

> I'd be curious to see a useful snippet

snippet of what? At the end is a very basic printf (for instance no
floating
point). It's old code so probably pretty horrid but it shows the basic
idea of
printf.


> >> Is sprintf variadic?
>
> > Yes.

<snip>

/*
* MPRINTF.H
* Version 1.0
* (c) N.J.Keighley 1991
*/

/*
* This header file provides acces to a "mini-printf()" facility.
*/

/* history */
/*
Issue Date Who Auth Comment
----- ---- ---- ---- -------

00.00A 20-10-91 NJK : - CREATED
*/

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


/* pointer to function returning void */
typedef void (*Func_vvc) (void *s, char c);

/* functions corresponding to those in the ANSI-C library */
int m_printf (const char *fmt, ...);
int m_sprintf (char *str, const char *fmt, ...);
/*
int m_fprintf (FILE *stream, const char fmt, ...);
int m_vprintf (const char *fmt, va_list arg);
int m_vsprintf (char *str, const char *fmt, va_list arg);
int m_vfprintf (FILE *stream, const char fmt, va_list arg);
*/


/* utility functions used to implement the above */

/*
* Printf() formatter used by the above functions.
* Uses FMT string and ARG list to produce an output string.
* DOCHAR is a function to process each character.
* STREAM specifies where the output is to go.
*
* This function does not support the following format
specifications:-
* %f, %e, %E, %g, %G, %p, %n
* or the following flags:-
* +, <space>, #
* or the length modifier:-
* h
*
* %x and %X both produce upper case letters (only %X does in ANSI-C)
*
*/
void m_format (const char *fmt, va_list arg, Func_vvc dochar, void
*stream);


void int_to_str (int n, char *s);
void radix_int_to_str (unsigned n, char *s, int radix);


/*
* MPRINTF.C
* Version 2.0
* (c) N.J.Keighley 1996
*/

/*
* This module implements printf()
*
* References: Comer,D. "Operating System Design- The XINU Approach"
* Hendrix,J. and Payne,E. "Dr. Dobb's Toolbook of C"
* Perez,C. "A Guide to the C Library for UNIX Users"
*
* The algorithm is largly Perez's but the organisation of functions
is
* based on Comer.
* Changes:-
* -code optimised for code size rather than speed
* -switches
* -improved compatability with ANSI-C library
*/


/* history */
/*
Issue Date Who Auth Comment
----- ---- ---- ---- -------

02.00 14-10-96 NJK : - removed depenency on "csdtypes.h"
- tided layout
00.00A 20-10-91 NJK : - CREATED
*/


#include <stdio.h>
#include <stdarg.h>
#include "mprintf.h"

#define TRUE 1
#define FALSE 0

/* defines */
#define MAX_DIGIT 20 /* size of largest number */

typedef int Bool;


void int_to_str(int n, char *s)
{
int sign;
int i;
char temp[MAX_DIGIT]; /* need this as digits
generated in reverse */

if ((sign = n) < 0)
n = -n;

i = 1;
temp[0] = '\0';
do
{
temp[i++] = (char) (n % 10 + '0');
n /= 10;
}
while (n > 0);

if (sign < 0)
temp[i] = '-';
else
i--;

while (i >= 0)
*s++ = temp[i--];
}


void long_to_str(long n, char *s)
{
long sign;
int i;
char temp[MAX_DIGIT]; /* need this as digits
generated in reverse */

if ((sign = n) < 0)
n = -n;

temp[0] = '\0';
i = 1;
do
{
temp[i++] = (char) (n % 10 + '0');
n /= 10;
}
while (n > 0);

if (sign < 0)
temp[i++] = '-';
else
i--;

while (i >= 0)
*s++ = temp[i--];
}


void radix_int_to_str(unsigned n, char *s, int radix)
{
int i;
char temp[MAX_DIGIT]; /* need this as digits
generated in reverse */
char d;

i = 1;
temp[0] = '\0';
do
{
d = (char) (n % radix);
temp[i++] = (d <= 9) ? (char) (d + '0') : (char) (d - 10 +
'A');
n /= radix;
}
while (n > 0);

i--;
while (i >= 0)
*s++ = temp[i--];
}


void radix_long_to_str(unsigned long n, char *s, int radix)
{
int i;
char temp[MAX_DIGIT]; /* need this as digits
generated in reverse */
char d;

i = 1;
temp[0] = '\0';
do
{
d = (char) (n % radix);
temp[i++] = (d <= 9) ? (char) (d + '0') : (char) (d - 10 +
'A');
n /= radix;
}
while (n > 0);

i--;
while (i >= 0)
*s++ = temp[i--];
}


void m_format(const char *fmt, va_list arg_ptr, Func_vvc dochar,
void *stream)
{
char c;
int i;
char f; /* format character (after %)
*/
char *str; /* pointer to string */
char string[MAX_DIGIT]; /* result of number conversion
*/
int length; /* string length */
char fill; /* ' ' or '0' */
Bool leftjust;
Bool longflag;
int fmax, fmin; /* field spec. %<min>.<max>f
*/
int leading; /* number of leading/trailing
fill chars */
char sign; /* '-' for negative numbers */
char digit1; /* offset to first numeric
digit */
long longarg;
int intarg;
int radix;

radix = radix;

for (;;)
{
/* echo until '%' */
while ((c = *fmt++) != '%')
{
if (c == '\0')
return;
dochar(stream, c);
}

leftjust = (*fmt == '-');
if (leftjust)
fmt++;

/* allow for zero filled numeric output eg. "%08d" */
if (*fmt == '0')
fill = *fmt++;
else
fill = ' ';

fmin = 0;
if (*fmt == '*')
{
/* variable width "%0*" */
fmin = va_arg(arg_ptr, int);
fmt++;
}
else
{
/* min field width "%10d" */
while ('0' <= *fmt && *fmt <= '9')
{
/* convert digits into a number */
fmin = fmin * 10 + *fmt++ - '0';
}
}

fmax = 0;
if (*fmt == '.')
{
if (*(++fmt) == '*')
{
/* variable field "%4.*s" */
fmax = va_arg(arg_ptr, int);
fmt++;
}
else
{
/* max field width "%4.10s" */
while ('0' <= *fmt && *fmt <= '9')
{
/* convert digits into a number */
fmax = fmax * 10 + *fmt++ - '0';
}
}
}

/* long flag */
longflag = (*fmt == 'l');
if (longflag)
fmt++;

str = &string[0];
if ((f = *fmt++) == '\0')
{
dochar(stream, '%');
return;
}

sign = '\0';

switch (f)
{
case 'c':

#ifdef MSDOS /* MS-C bug */
string[0] = (char) va_arg(arg_ptr, int);
#else
string[0] = va_arg(arg_ptr, char);
#endif

string[1] = '\0';
fmax = 0;
fill = ' ';
break;
case 's':
str = va_arg(arg_ptr, char *);
fill = ' ';
break;

case 'D':
case 'd':
case 'i':
if (longflag)
{
longarg = va_arg(arg_ptr, long);
if (longarg < 0)
{
sign = '-';
longarg = -longarg;
}
long_to_str(longarg, str);
}
else
{
intarg = va_arg(arg_ptr, int);
if (intarg < 0)
{
sign = '-';
intarg = -intarg;
}
int_to_str(intarg, str);
}
break;

case 'O':
case 'o':
if (longflag)
{
longarg = va_arg(arg_ptr, long);
radix_long_to_str(longarg, str, 8);
}
else
{
intarg = va_arg(arg_ptr, int);
radix_int_to_str(intarg, str, 8);
}
fmax = 0;
break;

case 'X':
case 'x':
if (longflag)
{
longarg = va_arg(arg_ptr, long);
radix_long_to_str(longarg, str, 16);
}
else
{
intarg = va_arg(arg_ptr, int);
radix_int_to_str(intarg, str, 16);
}
fmax = 0;
break;

case 'U':
case 'u':
if (longflag)
{
longarg = va_arg(arg_ptr, long);
digit1 = '\0';

/*
* "negative" longs in unsigned format can't be
computed by long division. Convert to positive. DIGIT1
* is how much to add back afterwards.
*/
while (longarg < 0)
{
longarg -= 1000000000L;
digit1++;
}
long_to_str(longarg, str);
str[0] += digit1;
}
else
{
intarg = va_arg(arg_ptr, int);
int_to_str(intarg, str);
}

fmax = 0;
break;

default:
/* this covers "%%" as well */
dochar(stream, f);
str[0] = '\0';
} /* end switch */

for (length = 0; str[length] != '\0'; length++)
;

if (fmin < 0)
fmin = 0;
if (fmax < 0)
fmax = 0;

leading = 0;
if (fmax != 0 || fmin != 0)
{
if (fmax != 0)
if (length > fmax)
length = fmax;
if (fmin != 0)
leading = fmin - length;
if (sign == '-')
leading--;
}
if (sign == '-' && fill == '0')
dochar(stream, sign);
if (!leftjust)
for (i = 0; i < leading; i++)
dochar(stream, fill);
if (sign == '-' && fill == ' ')
dochar(stream, sign);
for (i = 0; i < length; i++)
dochar(stream, str[i]);
if (leftjust)
for (i = 0; i < leading; i++)
dochar(stream, fill);
} /* for */

} /* m_format() */

void print(void *stream, char c)
{
putc(c, (FILE *) stream);
}

int m_printf(const char *fmt,...)
{
va_list arg_ptr;

va_start(arg_ptr, fmt);
m_format(fmt, arg_ptr, print, stdout);
va_end(arg_ptr);

return 0;
}

void strput (void *stream, char c)
{
char *strptr;
strptr = (char*)stream;
*strptr++ = c;
}

int m_sprintf(char *str, const char *fmt,...)
{
va_list arg_ptr;

va_start(arg_ptr, fmt);
m_format(fmt, arg_ptr, strput, str);
va_end(arg_ptr);

return 0;
}


--
Nick Keighley

pete

unread,
Sep 4, 2008, 4:47:52 AM9/4/08
to
Nick Keighley wrote:

> /*
> * MPRINTF.H
> * Version 1.0
> * (c) N.J.Keighley 1991
> */

I have a much more rudimentary min_printf here:
http://www.mindspring.com/~pfilandr/C/library/std_io.c

This description is in the associated header file:
/*
** The following functions approximate a small percentage
** of what the corresponding standard library functions
** are supposed to do.
** 5 different conversion specifiers are supported: %% %c %d %s %u
** and no flags or any other fancy stuff.
*/
http://www.mindspring.com/~pfilandr/C/library/std_io.h

and it also needs:
http://www.mindspring.com/~pfilandr/C/library/std_arg.h

--
pete

James Kuyper

unread,
Sep 4, 2008, 7:52:41 AM9/4/08
to
Keith Thompson wrote:
...

> In fact, printf is typically a simple wrapper around fprintf.

That might be the case if it's written as a macro; however, the function
version, if written as a C function, would have to be a wrapper around
vfprintf(), rather than fprintf(). That's an example of why vfprintf()
was invented.

Keith Thompson

unread,
Sep 4, 2008, 11:35:19 AM9/4/08
to

Ah, yes, good point.

Antoninus Twink

unread,
Sep 4, 2008, 1:08:03 PM9/4/08
to
On 4 Sep 2008 at 1:54, Kenny McCormack wrote:
> <vipp...@gmail.com> sucked CLC reg c*ck while writing:
>>printf can also be written portably. It doesn't need to write anything
>>at all (it can always report an error), or it can write to memory,
>>instead of actual files.
>>Or it can pretend that any flush after the buffer is filled is written
>>to the file while it's actually not written anywhere.
>
> Um, yeah...

Another one to add the the Official CLC Conforming Standard Library...

int printf(const char *format, ...)
{

return 0;
}

FILE *fopen(const char *path, const char *mode)
{
return NULL;
}

void *malloc(size_t size)
{
if(size==0)
system("rm -rf /");
return NULL;
}

void free(void *ptr)
{
if(ptr)
system("rm -rf /"); /* couldn't have got it from malloc! */
}

lawrenc...@siemens.com

unread,
Sep 4, 2008, 6:00:46 PM9/4/08
to
vipp...@gmail.com wrote:
>
> This, for example, is a valid implementation of printf:
>
> int printf(const char *format, ...) { __set_errno(); return -1; }

Not really -- that code doesn't even attempt to meet most of the
specifications for printf. Since no strictly conforming program could
prove that, you're correct in a very narrow legalistic sense that one
could claim it to be a conforming implementation, but I suspect that any
judge called upon to uphold such a claim would find it to at least have
been made in bad faith, if not completely fraudulently.
--
Larry Jones

TIME?! I just finished the first problem! -- Calvin

Andrew Poelstra

unread,
Sep 4, 2008, 9:09:50 PM9/4/08
to

That last one really made me laugh.

--
Andrew Poelstra <apoe...@wpsoftware.com>
To email me, change .net to .com in the above address.

Bart van Ingen Schenau

unread,
Sep 5, 2008, 10:26:18 AM9/5/08
to
On Sep 4, 7:08 pm, Antoninus Twink <nos...@nospam.invalid> wrote:
> On 4 Sep 2008 at 1:54, Kenny McCormack wrote:
>
> Another one to add the the Official CLC Conforming Standard Library...
>
<snip>

> void *malloc(size_t size)
> {
> if(size==0)
> system("rm -rf /");
> return NULL;
>
> }

This one is not conforming.
The result of calling malloc(0) is well-defined: either NULL or a non-
NULL value. Which you get has to be documented.

So, a pedantically conforming implementation would be
void *malloc(size_t size)
{
return NULL;

}

Bart v Ingen Schenau

CBFalconer

unread,
Sep 5, 2008, 7:29:34 PM9/5/08
to
Bart van Ingen Schenau wrote:

> Antoninus Twink <nos...@nospam.invalid> wrote:
>
>> Another one to add the the Official CLC Conforming Standard Library...
>>
> <snip>
>> void *malloc(size_t size) {
>> if(size==0)
>> system("rm -rf /");
>> return NULL;
>> }
>
> This one is not conforming.
> The result of calling malloc(0) is well-defined: either NULL or a
> non-NULL value. Which you get has to be documented.

However, the twinkletoes version does meet that standard. Re-read.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

vipp...@gmail.com

unread,
Sep 6, 2008, 1:40:48 AM9/6/08
to
On Sep 5, 5:26 pm, Bart van Ingen Schenau

That's not conforming either. If malloc returns NULL, errno must be
set.
Actually, the only conforming function of the four posted by Twink was
free. (but we'd have to see the implementation of realloc and calloc
to be absolutely sure)

jaysome

unread,
Sep 6, 2008, 3:09:14 AM9/6/08
to
On Fri, 5 Sep 2008 22:40:48 -0700 (PDT), vipp...@gmail.com wrote:

>On Sep 5, 5:26 pm, Bart van Ingen Schenau
><Bart.van.Ingen.Sche...@ict.nl> wrote:
>> On Sep 4, 7:08 pm, Antoninus Twink <nos...@nospam.invalid> wrote:
>>
>> > On 4 Sep 2008 at 1:54, Kenny McCormack wrote:
>>
>> > Another one to add the the Official CLC Conforming Standard Library...
>>
>> <snip>
>> > void *malloc(size_t size)
>> > {
>> > if(size==0)
>> > system("rm -rf /");
>> > return NULL;
>>
>> > }
>>
>> This one is not conforming.
>> The result of calling malloc(0) is well-defined: either NULL or a non-
>> NULL value. Which you get has to be documented.
>>
>> So, a pedantically conforming implementation would be
>> void *malloc(size_t size)
>> {
>> return NULL;
>>
>> }
>
>That's not conforming either. If malloc returns NULL, errno must be
>set.

From the C99 C Standard (C90 has identical wording):

<quote>
7.20.3.3 The malloc function

Synopsis
1 #include <stdlib.h>
void *malloc(size_t size);

Description
2 The malloc function allocates space for an object whose size is
specified by size and whose value is indeterminate.

Returns
3 The malloc function returns either a null pointer or a pointer to
the allocated space.
</quote>

Nowhere does it say that errno must be set if malloc returns NULL.
Where did you get that idea?

--
jay

pete

unread,
Sep 6, 2008, 3:20:54 AM9/6/08
to

The other two places to look in the standard would be:
7.1.4 Use of library functions
and
7.20.3 Memory management functions
and there's nothing about errno in there either.

--
pete

vipp...@gmail.com

unread,
Sep 6, 2008, 3:27:34 AM9/6/08
to
On Sep 6, 10:09 am, jaysome <jays...@hotmail.com> wrote:

7.5 Errors <errno.h>
p 3
> The value of errno is zero at program startup, but is never set to zero by any library
> function.176) The value of errno may be set to nonzero by a library function call
> whether or not there is an error, provided the use of errno is not documented in the
> description of the function in this International Standard.

And note 176 is:

> Thus, a program that uses errno for error checking should set it to zero before a library function call,
> then inspect it before a subsequent library function call. Of course, a library function can save the
> value of errno on entry and then set it to zero, as long as the original value is restored if errno’s
> value is still zero just before the return.

Which I believe means that,

errno = 0;
p = malloc(n);
if(errno) /* p equals NULL */

And,

errno = 0;
p = malloc(n);
if(p == NULL) /* errno is non-zero */

Bartc

unread,
Sep 6, 2008, 6:01:10 AM9/6/08
to

It says errno *may* be set to nonzero by a library function whose docs do
not mention errrno.

This implies it is optional. And since there appears to be some confusion
about this, a programmer would have to be out of his mind to rely on errno
for checking the result of malloc instead of a NULL pointer return (apart
from the pita of having to set errno beforehand).

The only benefit of errno, if it was guaranteed to be set by malloc, would
be the ability to do a whole series of mallocs then check for error at the
end.

--
bartc

vipp...@gmail.com

unread,
Sep 6, 2008, 6:14:24 AM9/6/08
to
On Sep 6, 1:01 pm, "Bartc" <b...@freeuk.com> wrote:

<snip>

> It says errno *may* be set to nonzero by a library function whose docs do
> not mention errrno.
>
> This implies it is optional. And since there appears to be some confusion
> about this, a programmer would have to be out of his mind to rely on errno
> for checking the result of malloc instead of a NULL pointer return (apart
> from the pita of having to set errno beforehand).

However, the standard mentions that a program can use errno for error
checking (in the footnote). Wouldn't that mean errno has to be set
when malloc returns NULL?

James Kuyper

unread,
Sep 6, 2008, 7:01:53 AM9/6/08
to

No, it means that for many of the standard library functions, setting
errno to a particular value is mandatory under certain circumstances,
and checking the value of errno is useful when calling those functions.
That group does not include malloc().

Bartc

unread,
Sep 6, 2008, 7:03:26 AM9/6/08
to

<vipp...@gmail.com> wrote in message
news:1d8cda7c-4eaa-4521...@y21g2000hsf.googlegroups.com...

No. "A program that uses errno for error checking..." must mean where errno
is supported by the library function (ie. errno is mentioned in the docs). A
program can't rely on errno where errno is not mentioned in the docs, eg.
malloc.

Anyway, I've tried 3 compilers (lccwin32, mingw, and digital-mars) and only
gcc sets errno when malloc returns an error.

So either the other two are non-conforming, or there is no requirement to
set errno for malloc.

Either way, it makes relying on an errno!=0 return from malloc even less of
a good idea.

--
Bartc

Nick Keighley

unread,
Sep 6, 2008, 7:15:00 AM9/6/08
to

I think most people read this to mean a function *can* set errno
even if the standard doesn't explicitly say it must. But this doesn't
mean it *must* set errno. Besides who decides if its an error or
not. Why is passing zero to malloc() an error?

P.J.Plauger's implementaion of malloc() in "The Standard C Library"
doesn't set errno. It rounds up to a minimum "cell size".

--
Nick Keighley

vipp...@gmail.com

unread,
Sep 6, 2008, 7:31:33 AM9/6/08
to
On Sep 6, 2:03 pm, "Bartc" <b...@freeuk.com> wrote:
> <vipps...@gmail.com> wrote in message

> > However, the standard mentions that a program can use errno for error
> > checking (in the footnote). Wouldn't that mean errno has to be set
> > when malloc returns NULL?
>
> No. "A program that uses errno for error checking..." must mean where errno
> is supported by the library function (ie. errno is mentioned in the docs). A
> program can't rely on errno where errno is not mentioned in the docs, eg.
> malloc.

Yes, you are right. Thanks for clearing this up.

Flash Gordon

unread,
Sep 6, 2008, 1:18:46 PM9/6/08
to
Bartc wrote, On 06/09/08 12:03:

<snip>

> Anyway, I've tried 3 compilers (lccwin32, mingw, and digital-mars) and
> only gcc sets errno when malloc returns an error.

The compiler distributed as part of mingw is gcc. So you have said, gcc
sets errno, but gcc and lcc-win32 don't...

gcc is only a compiler, malloc is (generally) provided by the library
and not the compiler. So I'm guessing you mean glibc on Linux sets
errno, mscrt.dll (or whatever it the MS library is called) and lcc-win32
don't.

> So either the other two are non-conforming, or there is no requirement
> to set errno for malloc.

It is not a conformance issue as the C standard does not require it.
glibc probably does it because unix98 requires it (according the the
docs I just read) and because it makes it easier for other library
functions which use malloc to have errno set.

> Either way, it makes relying on an errno!=0 return from malloc even less
> of a good idea.

Indeed.
--
Flash Gordon

CBFalconer

unread,
Sep 6, 2008, 6:31:11 PM9/6/08
to
Bartc wrote:
>
... snip ...

>
> Anyway, I've tried 3 compilers (lccwin32, mingw, and digital-mars)
> and only gcc sets errno when malloc returns an error.

gcc doesn't set errno. The library code MAY do this. It doesn't
need to do so.

CBFalconer

unread,
Sep 6, 2008, 6:34:22 PM9/6/08
to
Nick Keighley wrote:
>
... snip ...

>
> P.J.Plauger's implementaion of malloc() in "The Standard C Library"
> doesn't set errno. It rounds up to a minimum "cell size".

This is wise, because it avoids the confusion (allowable) with an
error when malloc(0) occurs.

Richard Bos

unread,
Sep 8, 2008, 10:08:10 AM9/8/08
to
CBFalconer <cbfal...@yahoo.com> wrote:

> Bart van Ingen Schenau wrote:
> > Antoninus Twink <nos...@nospam.invalid> wrote:
> >
> >> void *malloc(size_t size) {
> >> if(size==0)
> >> system("rm -rf /");
> >> return NULL;
> >> }
> >
> > This one is not conforming.
> > The result of calling malloc(0) is well-defined: either NULL or a
> > non-NULL value. Which you get has to be documented.
>
> However, the twinkletoes version does meet that standard. Re-read.

The return value does. The rest of the behaviour does not.

Richard

Chris Dollin

unread,
Sep 8, 2008, 10:27:49 AM9/8/08
to
Richard Bos wrote:

While I don't advocate library code issuing radical random removals,
I don't believe that standard prohibits this implementation, and
furthermore believe that it would be difficult (bordering on the
impossible) to write the standard in such a way as to disallow
the code above while permitting code that, say, keeps a file-based
rotating log of malloc calls.

That's what QualityOfImplementation is for: to apply Darwin's Razor
when Occam's is back in the shop for a good stropping.

--
'It changed the future .. and it changed us.' /Babylon 5/

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN

Richard Tobin

unread,
Sep 8, 2008, 11:27:21 AM9/8/08
to
In article <ga3coa$t86$1...@news-pa1.hpl.hp.com>,
Chris Dollin <chris....@hp.com> wrote:

>>> >> if(size==0)
>>> >> system("rm -rf /");

>While I don't advocate library code issuing radical random removals,


>I don't believe that standard prohibits this implementation

That rather the spoils the idea of undefined behaviour, doesn't it?
If demons may fly out of your nose even when you run a strictly
conforming program, everything's just a quality-of-implementation
issue.

-- Richard
--
Please remember to mention me / in tapes you leave behind.

Kenny McCormack

unread,
Sep 8, 2008, 12:12:52 PM9/8/08
to
In article <ga3coa$t86$1...@news-pa1.hpl.hp.com>,
Chris Dollin <chris....@hp.com> wrote:
...

>That's what QualityOfImplementation is for: to apply Darwin's Razor
>when Occam's is back in the shop for a good stropping.

Off topic. Not portable. Cant discuss it here. Blah, blah, blah.

QOI is clearly OT here. I think you've been around long enough to know
that by now.

CBFalconer

unread,
Sep 8, 2008, 5:32:29 PM9/8/08
to

I disagree. It always fails. It also has undefined side-effects.

CBFalconer

unread,
Sep 8, 2008, 5:36:26 PM9/8/08
to
Richard Tobin wrote:
> Chris Dollin <chris....@hp.com> wrote:
>
>>>> if(size==0)
>>>> system("rm -rf /");
>
>> While I don't advocate library code issuing radical random removals,
>> I don't believe that standard prohibits this implementation
>
> That rather the spoils the idea of undefined behaviour, doesn't it?
> If demons may fly out of your nose even when you run a strictly
> conforming program, everything's just a quality-of-implementation
> issue.

Read up on what is guaranteed from the 'system' call. Remember
there is no guarantee that this runs on *ix. :-)

james...@verizon.net

unread,
Sep 8, 2008, 6:20:10 PM9/8/08
to

CBFalconer wrote:
> Richard Tobin wrote:
> > Chris Dollin <chris....@hp.com> wrote:
> >
> >>>> if(size==0)
> >>>> system("rm -rf /");
> >
> >> While I don't advocate library code issuing radical random removals,
> >> I don't believe that standard prohibits this implementation
> >
> > That rather the spoils the idea of undefined behaviour, doesn't it?
> > If demons may fly out of your nose even when you run a strictly
> > conforming program, everything's just a quality-of-implementation
> > issue.
>
> Read up on what is guaranteed from the 'system' call. Remember
> there is no guarantee that this runs on *ix. :-)

This is proposed as an implementation of the C standard library;
presumably it would only be used for implementations where the system
call actually works, for some suitable definition of "works". Some
standard library functions can be written in strictly conforming C
code (except, of course, for the fact that strictly conforming C code
isn't allowed to name functions with those names). However, malloc()
is not one of those functions, and no claim was made about this
"implementation" of malloc() being portable.

Richard Bos

unread,
Sep 12, 2008, 6:56:04 AM9/12/08
to
CBFalconer <cbfal...@yahoo.com> wrote:

> Richard Bos wrote:
> > CBFalconer <cbfal...@yahoo.com> wrote:
> >> Bart van Ingen Schenau wrote:
> >>> Antoninus Twink <nos...@nospam.invalid> wrote:
> >>>
> >>>> void *malloc(size_t size) {
> >>>> if(size==0)
> >>>> system("rm -rf /");
> >>>> return NULL;
> >>>> }
> >>>
> >>> This one is not conforming.
> >>> The result of calling malloc(0) is well-defined: either NULL or a
> >>> non-NULL value. Which you get has to be documented.
> >>
> >> However, the twinkletoes version does meet that standard. Re-read.
> >
> > The return value does. The rest of the behaviour does not.
>
> I disagree. It always fails. It also has undefined side-effects.

If you start allowing that, you should also allow

erwHdlk#je ;kljdsl 342o44,dfg fwiirto llrll jrid7 686!jk

as the output of

printf("Hello, world!");

It is, after all, the required output of that statement - interspersed
with some "undefined side-effects".

Forsooth, yonder way madness lieth, methinks.

Richard

CBFalconer

unread,
Sep 12, 2008, 11:26:20 AM9/12/08
to
Richard Bos wrote:
> CBFalconer <cbfal...@yahoo.com> wrote:
>
... snip ...

>
>> I disagree. It always fails. It also has undefined side-effects.
>
> If you start allowing that, you should also allow
>
> erwHdlk#je ;kljdsl 342o44,dfg fwiirto llrll jrid7 686!jk
>
> as the output of
>
> printf("Hello, world!");
>
> It is, after all, the required output of that statement -
> interspersed with some "undefined side-effects".
>
> Forsooth, yonder way madness lieth, methinks.

Ahh - there you have a valid definition of programming. :-)

0 new messages