function definition

E

eotcl

Dear All!

While looking for the implementation of the printf function, I came
across the implementation
that used the following construct

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

What is the meaning of "..."? I didn't find it in K&R book, and
looking for "..." on the web doesn't seem to be productive. The actual
implementation of the function is a working piece of code,
I managed to compile it successfully.
Is it the way of introducing the generic programming paradigm within
the C language?

Thanks.
 
J

Joachim Schmitz

eotcl said:
Dear All!

While looking for the implementation of the printf function, I came
across the implementation
that used the following construct

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

What is the meaning of "..."? I didn't find it in K&R book, and
looking for "..." on the web doesn't seem to be productive.

Does searching for "ellipsis C" give better results?

e.g. http://en.wikipedia.org/wiki/Ellipsis#In_programming

That should lead you to 'variadic functions'

e.g.
http://en.wikipedia.org/wiki/Variadic_function#Variadic_functions_in_C.2C_Objective-C_and_C.2B.2B
The actual
implementation of the function is a working piece of code,
I managed to compile it successfully.
Is it the way of introducing the generic programming paradigm within
the C language?

Thanks.

Bye, Jojo
 
F

Flash Gordon

eotcl wrote, On 29/09/08 18:01:
Dear All!

While looking for the implementation of the printf function, I came
across the implementation
that used the following construct

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

What is the meaning of "..."? I didn't find it in K&R book, and

You need to improve your skills at looking things up...

Either that or you need to get the 2nd edition of K&R since it is one of
the "new" features introduced in 1989 or earlier. Don't throw away your
first edition copy though, it might be worth something ;-)

The index of my copy of K&R2 tells me to look on pages 155 and 202, and
I think the first of these two pages is the easier to learn from.
looking for "..." on the web doesn't seem to be productive. The actual

Try searching for "variable argument list" or "variable-length argument
lists" or the like, probably including the quotes. Be aware though that
a lot of what is on the web is wrong, often in ways you won't spot.
However, the comp.lang.c FAQ at http://c-faq.com/ is better than average
implementation of the function is a working piece of code,
I managed to compile it successfully.

That is a strange thing to be doing. Your implementation shoud come with
an implementation of printf that you can use!
Is it the way of introducing the generic programming paradigm within
the C language?

Generic programming in C is a far larger topic than ..., including the
use of macros and void* pointers.
 
T

Tinkertim

Dear All!

While looking for the implementation of the printf function, I came
across the implementation
that used the following construct

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

What is the meaning of "..."? I didn't find it in K&R book, and
looking for "..." on the web doesn't seem to be productive. The actual
implementation of the function is a working piece of code,
I managed to compile it successfully.
Is it the way of introducing the generic programming paradigm within
the C language?

Thanks.

In very lay terms, "..." means arguments that complement format.

For instance, this very simple function :

void psycho_printf(const char *format, ...)
{
va_list ap;

fprintf(stderr, "Charles Manson says: ");
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fprintf(stderr, "\n");

return;
}

This could be called like:

psycho_printf("%s %s %d", foo, bar, intfoo);

Or:

psycho_printf("%s", foo);

As you can see, the ellipsis allows for an undetermined amount of
arguments. The printf core in a C library is a corner case. My example
is bad, I don't return the number of characters not printed (or
anything useful) .. nor do I set errno. However it should help you see
the purpose of an ellipsis.

Hope this helps,
--Tim
 
E

eotcl

Thanks for this. I am not a native speaker and it didn't come to my
mind
to look for a translation of the "..." symbol.
Is "..." bound to stdarg.h, or can it be spearately without stdarg.h?
And is this construct a macro or part of the C language.

Thanks.
 
V

vippstar

Thanks for this. I am not a native speaker and it didn't come to my
mind
to look for a translation of the "..." symbol.
Is "..." bound to stdarg.h, or can it be spearately without stdarg.h?
And is this construct a macro or part of the C language.

.... is a punctuator. See 6.4.6 Punctuators of the C99 standard

Quote:

A punctuator is a symbol that has independent syntactic and semantic
signiï¬cance.
Depending on context, it may specify an operation to be performed
(which in turn may
yield a value or a function designator, produce a side effect, or some
combination thereof)
in which case it is known as an operator (other forms of operator also
exist in some
contexts). An operand is an entity on which an operator acts.

So yes; you don't need any headers to use it.
 
J

James Kuyper

eotcl said:
Thanks for this. I am not a native speaker and it didn't come to my
mind
to look for a translation of the "..." symbol.
Is "..." bound to stdarg.h, or can it be spearately without stdarg.h?
And is this construct a macro or part of the C language.

You need <stdarg.h> to define the function in C, but not for the
function prototype.
This is a fundamental feature of the C language, not a macro. If you
check the syntax for identifiers, you'll see that there's no way that
.... could qualify as the name of a macro.
 
N

Nick Keighley

In very lay terms, "..." means arguments that complement format.

if I understood this I'm sure I'd disagree. Ellipsis (...) means
the number and type of arguments is not specified. It allows you
to pass a variable number of arguments with number specified
(somehow), possibly by the fixed arguments.

void print (int n, ...)
{
int i
va_list args;
va_start(args, n);
for (i = 0; i < n; i++)
printf ("%d ", va_arg(args,int));
printf ("\n");
va_end(args)
}


I writte
 
T

Tinkertim

if I understood this I'm sure I'd disagree. Ellipsis (...) means
the number and type of arguments is not specified. It allows you
to pass a variable number of arguments with number specified
(somehow), possibly by the fixed arguments.

That's what I meant by complement, sorry. The number and type of
arguments in the case above is determined by the format passed, where
in your example its determined by a simple integer. %s %d determines
two arguments of varying types, where as n = 5 determines five
arguments of type int.

Complement is probably a bad choice of wording, however it appeared
that the OP is not a native speaker so I tried to speak generally.

Cheers,
--Tim
 
K

Keith Thompson

Tinkertim said:
That's what I meant by complement, sorry. The number and type of
arguments in the case above is determined by the format passed, where
in your example its determined by a simple integer. %s %d determines
two arguments of varying types, where as n = 5 determines five
arguments of type int.

Complement is probably a bad choice of wording, however it appeared
that the OP is not a native speaker so I tried to speak generally.

The point is that a printf-style format string isn't the only way to
determine the number and type of arguments that are supposed to be
passed (though I think it's the only method used by any of the
functions in the standard library). For example, I've seen variadic
functions that take a series of char* arguments, with the end of the
list marked by a (char*)NULL argument.
 
T

Tinkertim

The point is that a printf-style format string isn't the only way to
determine the number and type of arguments that are supposed to be
passed (though I think it's the only method used by any of the
functions in the standard library).

Your correct on the latter, I took a stroll through a few libc
implementations and only saw it in the printf core or things that use
it.
For example, I've seen variadic
functions that take a series of char* arguments, with the end of the
list marked by a (char*)NULL argument.

In that example, the function assumes all arguments to be char * type,
yes? You know your done when you hit a null argument. I'm not sure how
you could mix types without passing some kind of definition of the
incoming format.

I wasn't saying that a format was needed in all cases, just in cases
where arguments are of mixed types .. or is that what you were saying
that you've seen done? Sorry if I'm a little dense today :)

Cheers,
--Tim
 
N

Nick Keighley

Your correct on the latter, I took a stroll through a few libc
implementations and only saw it in the printf core or things that use
it.


In that example, the function assumes all arguments to be char * type,
yes? You know your done when you hit a null argument. I'm not sure how
you could mix types without passing some kind of definition of the
incoming format.

I wasn't saying that a format was needed in all cases, just in cases
where arguments are of mixed types .. or is that what you were saying
that you've seen done? Sorry if I'm a little dense today :)

Cheers,
--Tim






- Show quoted text -
 
N

Nick Keighley

The point is that a printf-style format string isn't the only way to
determine the number and type of arguments [in a varargs function]
that are supposed to be
passed (though I think it's the only method used by any of the
functions in the standard library).
yes

Your correct on the latter, I took a stroll through a few libc
implementations and only saw it in the printf core or things that use
it.
For example, I've seen variadic
functions that take a series of char* arguments, with the end of the
list marked by a (char*)NULL argument.

In that example, the function assumes all arguments to be char * type,
yes?

ones I've written do that
You know your done when you hit a null argument. I'm not sure how
you could mix types without passing some kind of definition of the
incoming format.

I wasn't saying that a format was needed in all cases, just in cases
where arguments are of mixed types .. or is that what you were saying
that you've seen done? Sorry if I'm a little dense today :)

again you could get devious and say the arguments were alternating
char*, int and the initial argument was a count of pairs.

I'm not saying these more esoteric variations are worth it
but I am saying you are *not* bound to printf() style arguments.
You could invent your own format (XML anyone!) or your
own types. I've written an error reporter for a comms system
where %p stood for PDU (a block of data transmitted over a comms
link) and it hex dumped the data.


don't quote sigs (the bit after "-- ")

--
Nick Keighley

As I recall, OSI dealt with TCP/IP by just admitting it into the spec
as a variation of existing levels. This is akin to dealing with an
Alien face hugger by allowing it to implant its embryo in your body.
 
K

Keith Thompson

Tinkertim said:
Your correct on the latter, I took a stroll through a few libc
implementations and only saw it in the printf core or things that use
it.


In that example, the function assumes all arguments to be char * type,
yes? You know your done when you hit a null argument. I'm not sure how
you could mix types without passing some kind of definition of the
incoming format.

I wasn't saying that a format was needed in all cases, just in cases
where arguments are of mixed types .. or is that what you were saying
that you've seen done? Sorry if I'm a little dense today :)

A format *string* is just one of many possible ways to specify the
arguments. Here's a rather contrived example:

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

enum arg_type { INT, DOUBLE, STRING, END };

void func(enum arg_type first, ...)
{
va_list ap;
enum arg_type next_arg_type = first;
va_start(ap, first);
do {
switch(next_arg_type) {
case INT: {
int i = va_arg(ap, int);
printf("int: %d\n", i);
break;
}
case DOUBLE: {
double d = va_arg(ap, double);
printf("double: %g\n", d);
break;
}
case STRING: {
char *s = va_arg(ap, char*);
printf("string: \"%s\"\n", s);
break;
}
case END: {
/* nothing */
}
}
next_arg_type = va_arg(ap, enum arg_type);
} while (next_arg_type != END);
va_end(ap);
}

int main(void)
{
func(INT, 42, STRING, "hello", DOUBLE, 1.23, END);
return 0;
}
 
T

Tinkertim

A format *string* is just one of many possible ways to specify the
arguments. Here's a rather contrived example:

Thanks, Keith! :) I've learned something new today. With a splash of
sanity, that is entirely convenient for corner cases.

Cheers,
--Tim
 
N

Nick Keighley

The point is that a printf-style format string isn't the only way to
determine the number and type of arguments [in a varargs function]
that are supposed to be
passed (though I think it's the only method used by any of the
functions in the standard library).

yes

<pedantic>
there's scanf() formats too
</pedantic>
 
J

James Kuyper

Tinkertim said:
In that example, the function assumes all arguments to be char * type,
yes? You know your done when you hit a null argument. I'm not sure how
you could mix types without passing some kind of definition of the
incoming format.

I wasn't saying that a format was needed in all cases, just in cases
where arguments are of mixed types .. or is that what you were saying
that you've seen done? Sorry if I'm a little dense today :)

There's many other ways to handle mixed argument types. For instance,
in the IMSL C library, variable arguments are passed in groups. Each
group starts with an enumeration constant that identifies the type of
the group. Since the enumeration constant always has a type of 'int',
the function knows how to parse it. Then, knowing the group type, the
library function knows the precise type of each of the remaining members
of the argument group. A code value of 0 marks the end of the argument list.

The only general statement that you can make is that, knowing the values
of each of the first n arguments, the variadic function must have enough
information to determine whether there is another argument, and if so,
what type it has.
 
J

Joachim Schmitz

Keith said:
The point is that a printf-style format string isn't the only way to
determine the number and type of arguments that are supposed to be
passed (though I think it's the only method used by any of the
functions in the standard library). For example, I've seen variadic
functions that take a series of char* arguments, with the end of the
list marked by a (char*)NULL argument.

Another example is POSIX's open() which has an optional 3rd argument (mode_t
mode), which is only needed (and looked at) depending on the value of the
2nd arg (int oflag, needs to have O_CREAT set).

Bye, Jojo
 
K

Keith Thompson

Nick Keighley said:
The point is that a printf-style format string isn't the only way to
determine the number and type of arguments [in a varargs function]
that are supposed to be
passed (though I think it's the only method used by any of the
functions in the standard library).

yes

<pedantic>
there's scanf() formats too
</pedantic>

Well, yes, but I assert that scanf's format strings are in the *style*
of printf's format strings.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top