Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > variadic functions

Reply
Thread Tools

variadic functions

 
 
Frank
Guest
Posts: n/a
 
      10-03-2009
I seem to be interested in places where C and fortran are different.
An example is:
#include <stdio.h>
#include <string.h>
int main() {
char s[10];
strcpy(s,"abcdefg");
strchr(s,'c')[1]='x';
printf("%s\n",s);
printf ("execution was here");
return 0;
}

Can someone say with clarity exactly what happens in the this line:
strchr(s,'c')[1]='x';
I think it's called array subscripting. Can someone post an example
of useful code that uses this feature?

Another thing we don't have are variadic functions. This was
particularly hard to understand from the K&R material, where I came
away from it thinking the ellipses were added by the book as opposed
to a language token.

#include <string.h>
int main(void)
{
int printf(const char *, ...);
char s[10];
strcpy(s,"abcdefg");
strchr(s,'c')[1]='x';
printf("%s\n",s);
printf ("execution was here");
return 0;
}
How is this program different from the first?
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      10-03-2009
Frank wrote:
> I seem to be interested in places where C and fortran are different.


I seem to hope the seeming resembles reality.

> An example is:
> #include <stdio.h>
> #include <string.h>
> int main() {
> char s[10];
> strcpy(s,"abcdefg");
> strchr(s,'c')[1]='x';
> printf("%s\n",s);
> printf ("execution was here");
> return 0;
> }
>
> Can someone say with clarity exactly what happens in the this line:
> strchr(s,'c')[1]='x';
> I think it's called array subscripting. Can someone post an example
> of useful code that uses this feature?


There are two things about C you need to know to make sense
of this.

The first is sometimes called The Rule: In most contexts
(all but two), writing the name of an array in an expression is
the same as writing a pointer to the array's first element.
That's why the strcpy() and strchr() and printf() calls' use of
the array name s is the same as writing &s[0], a pointer to the
zero'th element of the array s.

The second is that the indexing operator [] is *defined*
in terms of arithmetic on pointers: arr[j] means *(arr+j). This
causes giggles among immature schoolchildren when they suddenly
realize that addition is commutative, so *(arr+j) is the same as
*(j+arr), which is the same as j[arr]. Tee hee, snicker.

Since indexing is defined in terms of pointer arithmetic,
you don't need to do it on an actual array: You can do it with
any pointer and any integer (as long as the result is in range).
So arr[j] is legal, but so is p[j] when p is a pointer (or when
p is an integer and j is a pointer, tee hee, snicker). Apply
The Rule: p[j] means *(p+j). This use of the same notation with
both arrays and pointers is sometimes referred to as "equivalence
of pointers and arrays," which is slightly misleading because
they are not entirely equivalent. (Examine the values of
sizeof(s) and sizeof(&s[0]) to see one inequivalence.)

Okay, now you've got what you need to understand the line
that puzzles you. strchr() returns a pointer to char, a char*.
By The Rule, strchr(s,'c')[1] means *(strchr(s,'c')+1). As long
as strchr() doesn't return NULL (which it doesn't in your case),
the addition inside the parentheses is valid (it is *not* valid
to add or subtract from a NULL-valued pointer). So: strchr(s,'c')
returns a pointer to the 'c' at the [2] position in s, adding 1
produces a pointer to one place further along -- to the [3] spot
in s, where the 'd' resides, and then you store 'x' in that spot.

> Another thing we don't have are variadic functions. This was
> particularly hard to understand from the K&R material, where I came
> away from it thinking the ellipses were added by the book as opposed
> to a language token.
>
> #include <string.h>
> int main(void)
> {
> int printf(const char *, ...);
> char s[10];
> strcpy(s,"abcdefg");
> strchr(s,'c')[1]='x';
> printf("%s\n",s);
> printf ("execution was here");
> return 0;
> }
> How is this program different from the first?


It's sillier. The free-hand declaration of printf() is
correct and legal (in C99 it is not quite perfect, but still
legal as far as I know), but dumb. Many functions from the
Standard library *can* be declared free-hand, but it's silly
to do so. Some can be so declared and the program will work,
but you may find that it runs slower than if you'd included
the proper header. And there are several library functions
that *cannot* be declared free-hand, without their headers.

By the way, both programs exhibit implementation-defined
behavior: The "execution was here" line might or might not
actually show up on the output, or might show up only in part.
Always write a '\n' at the end of a text output stream.

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
 
 
 
Paul N
Guest
Posts: n/a
 
      10-03-2009
On 3 Oct, 10:17, "io_x" <(E-Mail Removed)> wrote:
> "Frank" <(E-Mail Removed)> ha scritto nel messaggionews:(E-Mail Removed)...
> > #include <string.h>
> > int main(void)
> > {
> > *int printf(const char *, ...);

>
> in what i know here you say to the linker to find
> "int printf(const char *, ...);"
> that could be different from printf in <stdio.h>?


I think you (io_x) could be making the same mistake here that I did
when I first learnt C. I thought that printf was "in" stdio.h, ie that
stdio.h contained the code to do printing. This is not the case.

Headers, such as stdio.h, contain text. This text can be included into
your program, and will have the same effect as if you included that
same text yourself in your program file. In the case of printf,
stdio.h contains a prototype, so that your program knows how to call
printf properly, but it doesn't have a clue what printf actually does.

Somewhere else, for example in a file called something.lib, there is
the actual machine code for printf, and when you link the program the
linker will find this and do the right thing with it, which will
normally involve copying the code into your executable.

My first compiler had six different .LIB files, but this wasn't so
that each only covered some of the functions, the way that .h files
do. They were because the computer had a choice of six different
"memory models" which each required slightly different versions of the
functions. Each .LIB file contained all of the functions.

Hope that helps.
Paul.
 
Reply With Quote
 
Frank
Guest
Posts: n/a
 
      10-03-2009
On Oct 2, 8:15*pm, Eric Sosman <(E-Mail Removed)> wrote:
> Frank wrote:
> > I seem to be interested in places where C and fortran are different.

>
> * * *I seem to hope the seeming resembles reality.


OT reminds of Poe:

And I hold within my hand
Grains of the golden sand-
How few! yet how they creep
Through my fingers to the deep,
While I weep- while I weep!
O God! can I not grasp
Them with a tighter clasp?
O God! can I not save
One from the pitiless wave?
Is all that we see or seem
But a dream within a dream?
>
>
>
> > An example is:
> > #include <stdio.h>
> > #include <string.h>
> > int main() {
> > * *char s[10];
> > * *strcpy(s,"abcdefg");
> > * *strchr(s,'c')[1]='x';
> > * *printf("%s\n",s);
> > * *printf ("execution was here");
> > * *return 0;
> > }

>
> > Can someone say with clarity exactly what happens in the this line:
> > * *strchr(s,'c')[1]='x';
> > I think it's called array subscripting. *Can someone post an example
> > of useful code that uses this feature?

>
> * * *There are two things about C you need to know to make sense
> of this.
>
> * * *The first is sometimes called The Rule: In most contexts
> (all but two), writing the name of an array in an expression is
> the same as writing a pointer to the array's first element.
> That's why the strcpy() and strchr() and printf() calls' use of
> the array name s is the same as writing &s[0], a pointer to the
> zero'th element of the array s.
>
> * * *The second is that the indexing operator [] is *defined*
> in terms of arithmetic on pointers: arr[j] means *(arr+j). *This
> causes giggles among immature schoolchildren when they suddenly
> realize that addition is commutative, so *(arr+j) is the same as
> *(j+arr), which is the same as j[arr]. *Tee hee, snicker.
>
> * * *Since indexing is defined in terms of pointer arithmetic,
> you don't need to do it on an actual array: You can do it with
> any pointer and any integer (as long as the result is in range).
> So arr[j] is legal, but so is p[j] when p is a pointer (or when
> p is an integer and j is a pointer, tee hee, snicker). *Apply
> The Rule: p[j] means *(p+j). *This use of the same notation with
> both arrays and pointers is sometimes referred to as "equivalence
> of pointers and arrays," which is slightly misleading because
> they are not entirely equivalent. *(Examine the values of
> sizeof(s) and sizeof(&s[0]) to see one inequivalence.)
>
> * * *Okay, now you've got what you need to understand the line
> that puzzles you. *strchr() returns a pointer to char, a char*.
> By The Rule, strchr(s,'c')[1] means *(strchr(s,'c')+1). *As long
> as strchr() doesn't return NULL (which it doesn't in your case),
> the addition inside the parentheses is valid (it is *not* valid
> to add or subtract from a NULL-valued pointer). *So: strchr(s,'c')
> returns a pointer to the 'c' at the [2] position in s, adding 1
> produces a pointer to one place further along -- to the [3] spot
> in s, where the 'd' resides, and then you store 'x' in that spot.


Ok. Thanks for your response, Eric. I struggle with this every time
I take up C again (but less and less). It really me understand to
have someone "talk through" an idiom.
> > Another thing we don't have are variadic functions. *This was
> > particularly hard to understand from the K&R material, where I came
> > away from it thinking the ellipses were added by the book as opposed
> > to a language token.

>
> > #include <string.h>
> > int main(void)
> > {
> > * int printf(const char *, ...);
> > * char s[10];
> > * strcpy(s,"abcdefg");
> > * strchr(s,'c')[1]='x';
> > * printf("%s\n",s);
> > * printf ("execution was here");
> > * return 0;
> > }
> > How is this program different from the first?

>
> * * *It's sillier. *The free-hand declaration of printf() is
> correct and legal (in C99 it is not quite perfect, but still
> legal as far as I know), but dumb. *Many functions from the
> Standard library *can* be declared free-hand, but it's silly
> to do so. *Some can be so declared and the program will work,
> but you may find that it runs slower than if you'd included
> the proper header. *And there are several library functions
> that *cannot* be declared free-hand, without their headers.


Which ones?
>
> * * *By the way, both programs exhibit implementation-defined
> behavior: The "execution was here" line might or might not
> actually show up on the output, or might show up only in part.
> Always write a '\n' at the end of a text output stream.


Right. These prototypes are also very implementation-specific, so in
general, you'd want the the prototype that the vendor thinks you
need. Is everything here kosher:

#include <string.h>
#include <stdlib.h>
int printf(const char *, ...);
void print_it(char *);
int main(void)
{


char * p;

p = malloc(100);
strcpy(p, "ABQ Balloon Fest today");

print_it( p );
free(p);

return 0;
}




 
Reply With Quote
 
Frank
Guest
Posts: n/a
 
      10-03-2009
On Oct 3, 9:01*am, Paul N <(E-Mail Removed)> wrote:
> On 3 Oct, 10:17, "io_x" <(E-Mail Removed)> wrote:
>
> > "Frank" <(E-Mail Removed)> ha scritto nel messaggionews:(E-Mail Removed)...
> > > #include <string.h>
> > > int main(void)
> > > {
> > > *int printf(const char *, ...);

>
> > in what i know here you say to the linker to find
> > "int printf(const char *, ...);"
> > that could be different from printf in <stdio.h>?

>
> I think you (io_x) could be making the same mistake here that I did
> when I first learnt C. I thought that printf was "in" stdio.h, ie that
> stdio.h contained the code to do printing. This is not the case.
>
> Headers, such as stdio.h, contain text. This text can be included into
> your program, and will have the same effect as if you included that
> same text yourself in your program file. In the case of printf,
> stdio.h contains a prototype, so that your program knows how to call
> printf properly, but it doesn't have a clue what printf actually does.
>
> Somewhere else, for example in a file called something.lib, there is
> the actual machine code for printf, and when you link the program the
> linker will find this and do the right thing with it, which will
> normally involve copying the code into your executable.
>
> My first compiler had six different .LIB files, but this wasn't so
> that each only covered some of the functions, the way that .h files
> do. They were because the computer had a choice of six different
> "memory models" which each required slightly different versions of the
> functions. Each .LIB file contained all of the functions.
>
> Hope that helps.
> Paul.


It helps me, Paul I think what you're getting at here is how the
machine executes a library function and that what you're saying is
that stdio.h is long gone by this point and that the linker knew where
to find the correctly-prototyped function and paste in the code.

I think io_x was getting at this case:


#include <string.h>
#include <stdlib.h>
int printf(const char *, ...);

int main(void)
{


char * p;

p = malloc(100);
strcpy(p, "ABQ Balloon Fest today");

printf( p );
free(p);

return 0;
}


int printf(char * r, ...)
{
printf ("in function\n");
printf("%s\n", r);
}

I don't know what happens here during compilation or execution.
 
Reply With Quote
 
Frank
Guest
Posts: n/a
 
      10-03-2009
On Oct 3, 10:42*am, Frank <(E-Mail Removed)> wrote:

> I don't know what happens here during compilation or execution.


I meant with stdio.h included. It draws errors from my
implementation:


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int printf(const char *, ...);

int main(void)
{

char * p;

p = malloc(100);
strcpy(p, "ABQ Balloon Fest today");

printf( p );
free(p);

return 0;

}

int printf(char * r, ...)
{
printf ("in function\n");
printf("%s\n", r);

}

Wedit output window build: Sat Oct 03 11:56:39 2009
Error c:\lcc\source\nick2.c: 23 redefinition of 'printf'
Error c:\lcc\source\nick2.c: 5 Previous definition of 'printf' here
Warning c:\lcc\source\nick2.c: 27 missing return value
Compilation + link time:0.0 sec, Return code: 1


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      10-03-2009
Frank wrote:
> On Oct 2, 8:15 pm, Eric Sosman <(E-Mail Removed)> wrote:
>> [...] And there are several library functions
>> that *cannot* be declared free-hand, without their headers.

>
> Which ones?


This would be a good time for you to review the Standard
library. It's grown a good deal with C99, but even in the C90
version you should be able to find several examples. Why don't
you just start trying to write free-hand declarations for all
the library functions you can think of, no headers allowed, and
see how far you get before running into a snag?

> Right. These prototypes are also very implementation-specific, so in
> general, you'd want the the prototype that the vendor thinks you
> need.


No, the prototypes are as dictated by the Standard, and
cannot be implementation-specific (aside from trivial matters
like names of function parameters, harmless typedef aliases,
and so on). There may be implementation-specific "magic"
accompanying the prototypes, living elsewhere in the declarations
or in accompanying macros and such. But the prototypes themselves
are inviolate.

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
Frank
Guest
Posts: n/a
 
      10-03-2009
On Oct 3, 12:32*pm, Eric Sosman <(E-Mail Removed)> wrote:
> Frank wrote:
> > On Oct 2, 8:15 pm, Eric Sosman <(E-Mail Removed)> wrote:
> >> [...] And there are several library functions
> >> that *cannot* be declared free-hand, without their headers.

>
> > Which ones?

>
> * * *This would be a good time for you to review the Standard
> library. *It's grown a good deal with C99, but even in the C90
> version you should be able to find several examples. *Why don't
> you just start trying to write free-hand declarations for all
> the library functions you can think of, no headers allowed, and
> see how far you get before running into a snag?


That might be a good way to test whether you *really* know these
functions. I can say with confidence that I do not. The only
reference to the Standard Library in Unleashed is the book of the same
name by PJ Plauger. Any opinions on this book?

>
> > Right. These prototypes are also very implementation-specific, so in
> > general, you'd want the the prototype that the vendor thinks you
> > need.

>
> * * *No, the prototypes are as dictated by the Standard, and
> cannot be implementation-specific (aside from trivial matters
> like names of function parameters, harmless typedef aliases,
> and so on). *There may be implementation-specific "magic"
> accompanying the prototypes, living elsewhere in the declarations
> or in accompanying macros and such. *But the prototypes themselves
> are inviolate.


Hmm. I guess the sentiment arose from difference between
implementations in stdio.h that were #defined.

int printf(const char * restrict format, ...);
p. 430, 1256.pdf
is the Standard way that this is defined. You claim that this is
essentially
int printf(const char *, ...);
Right?

 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      10-04-2009
Frank wrote:
> On Oct 3, 12:32 pm, Eric Sosman <(E-Mail Removed)> wrote:
>> Frank wrote:
>>> On Oct 2, 8:15 pm, Eric Sosman <(E-Mail Removed)> wrote:
>>>> [...] And there are several library functions
>>>> that *cannot* be declared free-hand, without their headers.
>>> Which ones?

>> This would be a good time for you to review the Standard
>> library. It's grown a good deal with C99, but even in the C90
>> version you should be able to find several examples. Why don't
>> you just start trying to write free-hand declarations for all
>> the library functions you can think of, no headers allowed, and
>> see how far you get before running into a snag?

>
> That might be a good way to test whether you *really* know these
> functions. I can say with confidence that I do not.


I'd say I "know" about fifty percent of the Standard
library, taking "know" to mean "I never consult a reference
any more." I "sort of know" another twenty-five percent,
meaning that I can use the functions most of the time but
need to crack open a book for corner cases. And there's
another twenty-five percent that I just plain don't use and
can't claim familiarity with: Most of the new floating-point
and complex-variable functions of C99, the wide-character
functions, and the locale functions come to mind as stuff
my work simply doesn't involve. Even so, I know they exist
and would know that cracking a book would make them available
to me should the need ever arise. (Oh, and bsearch(): I find
it harder to remember how to call bsearch() than just to write
the search in open code.)

> The only
> reference to the Standard Library in Unleashed is the book of the same
> name by PJ Plauger. Any opinions on this book?


If by "this book" you mean PJ Plauger's "The Standard C
Library," I think it excellent. C90-centered, but as I said
above most of the C99 additions are foreign to me anyhow.

If by "this book" you mean "C Unleashed" by a cast of
thousands, I haven't read it and have no opinion.

> Hmm. I guess the sentiment arose from difference between
> implementations in stdio.h that were #defined.


I don't know what you mean by this.

> int printf(const char * restrict format, ...);
> p. 430, 1256.pdf
> is the Standard way that this is defined. You claim that this is
> essentially
> int printf(const char *, ...);
> Right?


No, they're different. One names the fixed parameter and
has the `restrict' qualifier; the other doesn't. I claim that
the presence of the name makes no difference at all, barring
things like pre-existing macro definitions named `format'. As
to whether it's legal to omit the `restrict', I *believe* it is
but it's more a matter of faith than of reason.

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
Antoninus Twink
Guest
Posts: n/a
 
      10-04-2009
On 4 Oct 2009 at 1:43, Eric Sosman wrote:
> If by "this book" you mean "C Unleashed" by a cast of
> thousands, I haven't read it and have no opinion.


Very delicately put, Eric.

If you and Frank are interested, I'd advise reading some of the threads
started by Han from China earlier this year, pointing out some of the
basic errors in the chapters by Richard Heath Field.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Call again a variadic function (... variable number of arguments)with same arguments that its variadic wrapper moreau.steve@gmail.com C Programming 3 12-31-2008 07:13 AM
variadic function calling variadic function goldfita@signalsguru.net C Programming 5 05-03-2006 05:23 PM
Using variadic functions within variadic functions pinkfloydhomer@gmail.com C Programming 2 02-27-2006 05:47 AM
Variadic functions calling variadic functions with the argument list, HLL bit shifts on LE processors Ross A. Finlayson C Programming 19 03-10-2005 03:57 AM
is casting a variadic function to a non-variadic one legal? Colin Walters C Programming 2 02-13-2004 10:55 PM



Advertisments