variadic functions

F

Frank

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?
 
E

Eric Sosman

Frank said:
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.
 
P

Paul N

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.
 
F

Frank

     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;
}
 
F

Frank

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.
 
F

Frank

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
 
E

Eric Sosman

Frank said:
[...] 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.
 
F

Frank

Frank said:
[...] 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?
     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?
 
E

Eric Sosman

Frank said:
Frank said:
[...] 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.
 
A

Antoninus Twink

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.
 
F

Frank

Frank said:
Frank 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.

What version does it have to be? I can pay between 7 and 54 dollars
for this on Amazon. I don't want anything that is tragically
outdated.
     I don't know what you mean by this.

The #defines are more implementation specific than the function
prototypes, by necessity.
     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.

I wish I knew how to bet on faith versus reason. Apparently, none of
the functions you referred to in your top-snipped post are in
stdlib.h:



#ifndef __stdlib_h__
#define __stdlib_h__
#include <stddef.h>
#include <_syslist.h>
#define MB_CUR_MAX 2
#define _MAX_PATH 260
#define _MAX_FNAME 256
#define _MAX_EXT 256
#define _MAX_DRIVE 3
#define _MAX_DIR 256
#undef RAND_MAX
#define RAND_MAX 0x7FFF
typedef struct {
int quot; /* quotient */
int rem; /* remainder */
} div_t;

typedef struct {
long quot; /* quotient */
long rem; /* remainder */
} ldiv_t;
typedef struct {
long long quot;
long long rem;
} lldiv_t;
#undef NULL
#define NULL ((void *)0)
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#endif

void abort(void);
int abs(int);
long long llabs(long long);
int atexit(void (*_func)(void));
double atof(const char *);
int atoi(const char *);
char *itoa(int,char *,int);
char *ltoa(long,char *,int);
void * bsearch(const void * _key,const void * _base, size_t _nmemb,
size_t _size,
int (*_compar)(const void *,const void *));
void * calloc(size_t _nmemb, size_t _size);
#if __LCCOPTIMLEVEL > 0
inline div_t __declspec(naked) div(int a,int b)
{
_asm("\tmovl\t(%esp),%eax");
_asm("\tmovl\t4(%esp),%ecx");
_asm("\tcdq");
_asm("\tidivl\t%ecx");
}
#else
div_t div(int _numer, int _denom);
#endif
void exit(int _status);
void _exit(int status);
#define _Exit _exit
void free(void *);


double strtod(const char *restrict nptr,char ** restrict endptr);
long double strtold(const char *restrict nptr,char ** restrict
endptr);
float strtof(const char *restrict nptr,char ** restrict endptr);
char * getenv(const char *_string);
long labs(long);
ldiv_t ldiv(long _numer, long _denom);
lldiv_t lldiv(long long numer,long long denom);
void * malloc(size_t _size);
void qsort(void * _base, size_t _nmemb, size_t _size, int(*_compar)
(const void *, const void *));
int rand(void);
void * realloc(void * _r, size_t _size);
void srand(unsigned _seed);
double strtod(const char *_n, char **_endvoid);
long double strtold(const char *,char **);
long long strtoll(const char *,char **,int);
unsigned long long strtoull(const char *,char **,int);
long strtol(const char *_n, char **_endvoid, int _base);
unsigned long strtoul(const char *_n, char **_end, int _base);
int system(const char *_string);
int putenv(const char *_string);
char * _gcvt(double,int,char *);
char * _fcvt(double,int,int *,int *);
char * ecvt(double,int,int *,int *);
int mbstowcs(wchar_t *,char *,size_t);
size_t wcstombs( char *mbstr, const wchar_t *wcstr, size_t count );
int mblen(char *,size_t);
int mbstrlen(char *s);
long atol(char *_nptr);

#ifndef __ANSIC__ONLY__
#include "safelib.h"

typedef void (*constraint_handler_t)( const char * restrict msg, void
* restrict ptr, errno_t error);
double frand(void);
constraint_handler_t set_constraint_handler_s( constraint_handler_t
handler);
constraint_handler_t get_constraint_handler_s( void );
void abort_handler_s( const char * restrict msg, void * restrict ptr,
errno_t error);
void ignore_handler_s( const char * restrict msg, void * restrict ptr,
errno_t error);
errno_t getenv_s(size_t * restrict len, char * restrict value, rsize_t
maxsize, const char * restrict name);
void *bsearch_s(const void *key, const void *base, rsize_t nmemb,
rsize_t size, int (*compar)(const void *k, const void *y, void
*context), void *context);
errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size, int (*compar)
(const void *x, const void *y, void *context), void *context);
errno_t wctomb_s(int * restrict status, char * restrict s, rsize_t
smax, wchar_t wc);
errno_t mbstowcs_s(size_t * restrict retval, wchar_t * restrict dst,
rsize_t dstmax, const char * restrict src, rsize_t len);
errno_t wcstombs_s(size_t * restrict retval, char * restrict dst,
rsize_t dstmax, const wchar_t * restrict src, rsize_t len);


#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
double wtof(const wchar_t *);
char *_fullpath( char *absPath, const char *relPath, size_t
maxLength );
void _makepath(char *path, const char *drive, const char *dir, const
char *fname, const char *ext );
void _splitpath(const char*, char*, char*, char*, char*);

#define _OUT_TO_DEFAULT 0
#define _OUT_TO_STDERR 1
#define _OUT_TO_MSGBOX 2
#define _REPORT_ERRMODE 3

extern int _sleep(unsigned long);
#define sleep _sleep
#define _mbstrlen mbstrlen
#define CRTAPI1
#define _fmode *(_imp___fmode_dll)
extern int _fmode;
extern char ***_imp___environ_dll;
#define _environ (*_imp___environ_dll)
extern unsigned int _osver;
extern unsigned int *(_imp___osver);
#define _osver *(_imp___osver)
extern unsigned int _winmajor;
extern unsigned int *(_imp___winmajor);
#define _winmajor *(_imp___winmajor)
extern unsigned int _winminor;
extern unsigned int *(_imp___winminor);
#define _winminor *(_imp___winminor)
extern unsigned int _winver;
extern unsigned int *(_imp___winver);
#define _winver *(_imp___winver)
void _searchenv(char *,char *,char *);
wchar_t * _itow (int, wchar_t *, int);
wchar_t * _ltow (long, wchar_t *, int);
unsigned short * _ultow (unsigned long, unsigned short *, int);
double wcstod(const wchar_t *, wchar_t **);
long wcstol(const wchar_t *, wchar_t **, int);
int wctomb(char *s,wchar_t wchar);
unsigned long wcstoul(const wchar_t *, wchar_t **, int);
wchar_t * _wgetenv(const wchar_t *);
int _wsystem(const wchar_t *);
int _wtoi(const wchar_t *);
long _wtol(const wchar_t *);
// Contains argv[0]
extern char * __declspec(dllimport) _pgmptr;
int _stdcall _lrotl(unsigned long,unsigned int);
int _stdcall _lrotr(unsigned int,unsigned int);
char *_i64toa(long long,char *,int);
char *_ui64toa(unsigned long long,char *,int);
long long _atoi64(const char *);
#define atoi64 _atoi64
char *_ultoa(unsigned long,char *,int);
unsigned short *_ultow(unsigned long,unsigned short *,int);
#define ultoa _ultoa
#define ultow _ultow
int _stdcall _System(const char *cmd,int nCmdShow);
#endif
#endif /* _STDLIB_H_ */



#include <stdio.h>
#include <string.h>
void Usage(char *programName)
{
fprintf(stderr,"%s usage:\n",programName);
/* Modify here to add your usage message when the program is
* called without arguments */
}

/* returns the index of the first argument that is not an option; i.e.
does not start with a dash or a slash
*/
int HandleOptions(int argc,char *argv[])
{
int i,firstnonoption=0;

for (i=1; i< argc;i++) {
if (argv[0] == '/' || argv[0] == '-') {
switch (argv[1]) {
/* An argument -? means help is requested */
case '?':
Usage(argv[0]);
break;
case 'h':
case 'H':
if (!stricmp(argv+1,"help")) {
Usage(argv[0]);
break;
}
/* If the option -h means anything else
* in your application add code here
* Note: this falls through to the default
* to print an "unknow option" message
*/
/* add your option switches here */
default:
fprintf(stderr,"unknown option %s\n",argv);
break;
}
}
else {
firstnonoption = i;
break;
}
}
return firstnonoption;
}

int main(int argc,char *argv[])
{
if (argc == 1) {
/* If no arguments we call the Usage routine and exit */
Usage(argv[0]);
return 1;
}
/* handle the program options */
HandleOptions(argc,argv);
/* The code of your application goes here */
return 0;
}

This compiles on lcc.
 
F

Frank

Very delicately put, Eric.

I won't have you bagging on Unleashed on my threads. It is certainly
a dubious achievement to have set a record on errata.
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.

What if help if he called himself "Ludwid van der Heide?" What
happened to Han?
 
N

Nick Keighley

I won't have you bagging on Unleashed on my threads.  

what does "bagging" mean?
In what way is it your thread?

It is certainly
a dubious achievement to have set a record on errata.

Is its errata particulary large? Perhaps this reflects some
diligence on behalf of the errata producer. One way to avoid
a large errata is simply not to publish one...


I advise you also read some less biased review before making your mind
up.
Try Amazon and ACCU

What if help if he called himself "Ludwid van der Heide?"  What
happened to Han?

? what?
 
E

Eric Sosman

As I don't read "Twink," I didn't see this attempt to
twist my words until Frank quoted it. Lest any doubt arise
from "Twink's" attempt to count my vote in his column, I have
not cast a vote at all. "No opinion" means *no* opinion,
positive, negative, or neutral.

I do, however, have an opinion about "Twink."
 
E

Eric Sosman

Frank said:
What version does it have to be? I can pay between 7 and 54 dollars
for this on Amazon. I don't want anything that is tragically
outdated.

Aren't you the one who used the definite pronoun "this" to
refer to the book? Rather than "a" book or "some book or other?"
If you didn't have a particular book in mind, you shouldn't have
used "this."

As for versions, I have no idea what you consider "tragically
outdated." My copy is copyrighted 1992. A lot of people I know
take their daily guidance from a book that has outsold all others
(or has a reasonable claim to have done so) but is much older.
[... big snip ...]
This compiles on lcc.

Maybe I'm dense today (it's been a difficult day), but I don't
see the relevance of this gobbet of non-portable code.
 
F

Frank

     Aren't you the one who used the definite pronoun "this" to
refer to the book?  Rather than "a" book or "some book or other?"
If you didn't have a particular book in mind, you shouldn't have
used "this."

     As for versions, I have no idea what you consider "tragically
outdated."  My copy is copyrighted 1992.  A lot of people I know
take their daily guidance from a book that has outsold all others
(or has a reasonable claim to have done so) but is much older.

I seem to know less about libraries than most programmers, so I'll
look forward to getting this. All I saw on Amazon was the 1992
version. I ended up going with one that cost ten bucks and then four
to ship.

I think I share with you a complete indifference to wide character
stuff. It ate a lot of text in H&S V and it all looked the same.
(There might a hint of racism in this sentiment. I'm still recovering
as a bigot.)
     Maybe I'm dense today (it's been a difficult day), but I don't
see the relevance of this gobbet of non-portable code.

I thought you said that there existed functions that are different
than printf() in that you can't duplicate the task of #including the
appropriate header by writing out the defintion yourself. Lcc's
stdlib.h seamed to work just as well pasted in globally as opposed to
#including it.
 
N

Nick Keighley

     As for versions, I have no idea what you consider "tragically
outdated."  My copy is copyrighted 1992.  A lot of people I know
take their daily guidance from a book that has outsold all others
(or has a reasonable claim to have done so) but is much older.

Mao's Little Red Book tell you to program in C?!


"It is well known that when you do anything, unless you understand
its actual circumstances, its nature and its relations to other
things,
you will not know the laws governing it, or know how to do it, or be
able
to do it well."

"Problems of Strategy in China's Revolutionary War" 1936
 
N

Nick Keighley

I seem to know less about libraries than most programmers, so I'll
look forward to getting this.

Plauger's book? Excellent book. By the time you've ploughed throgh
that you'll know a lot about the standard C library. For reference
I use Harbison & Steel or just google it.

I thought you said that there existed functions that are different
than printf() in that you can't duplicate the task of #including the
appropriate header by writing out the defintion yourself.  


I haven't a clue what that means. What are "function that are
different
than [sic] printf()"? What does "can't duplicate the task of
#including the
appropriate header by writing out the defintion yourself" mean? For
any
standard library function you can write out the prototype yourself
rather than including the header. This is tedious and error prone
so why would you do that?

Lcc's
stdlib.h seamed to work just as well pasted in globally as opposed to
#including it.

that's what #include does. Why would you do that?

Really. You seem to be hunting for weird ways to do things when the
standard
ways work fine. Perhaps Plauger will help you.
 
E

Eric Sosman

Frank said:
Frank said:
[...]
This compiles on lcc.
Maybe I'm dense today (it's been a difficult day), but I don't
see the relevance of this gobbet of non-portable code.

I thought you said that there existed functions that are different
than printf() in that you can't duplicate the task of #including the
appropriate header by writing out the defintion yourself. Lcc's
stdlib.h seamed to work just as well pasted in globally as opposed to
#including it.

Okay; it was the reference to a "list" of functions that
threw me, because I don't recall seeing a list.

The Standard library contains some functions that cannot
be correctly declared "free-hand," that is, without their
Standard headers. It also contains functions that *can* be
so declared, although it's silly to do so.

The code you showed seemed to be mostly a copy-and-paste
of some implementation's <stdlib.h>, and I guess you consider
that a "free-hand" declaration of the contained functions. For
some -- atof(), for example -- the declaration is just fine and
you could (if in a silly mood) just write that line in your
code and buzz merrily along. But for many, the declaration is
specific to the implementation at hand, and would not work with
others; you'll have written a declaration of Frobozz Magic C's
version of ldiv(), not of Standard C's ldiv().

Well, actually, it's not the declaration of ldiv() itself
that's the problem -- but what about ldiv()'s result? You know
that it returns a struct ldiv_t, but where can you find that
struct type declared? A struct ldiv_t is quite likely arranged
in a way that's convenient to the hardware, and if you moved
your program to different hardware the arrangement would differ.
Claim: The only way to get a struct ldiv_t declaration that
works everywhere is to include <stdlib.h> and let the header
tell you about the local customs.

Then there's rand() -- easy enough to declare portably, but
what will you do if you need the value of RAND_MAX? And it's
easy to write a portable declaration of exit(), and you could
avoid EXIT_SUCCESS by always using zero, but what if you need
the value of EXIT_FAILURE? How will you write a declaration of
malloc(), without knowing what size_t is? (In this case you
could cheat by including one of the other headers that defines
size_t and then writing your malloc() declaration without using
<stdlib.h> itself, but that's a subterfuge.)

There: I've shown you a few <stdlib.h> functions that cannot
be properly declared without <stdlib.h>, and a few that can be
declared but can't be used to their fullest without it. You will
find other similar examples in other Standard headers -- and some
of those functions are not in the least bit esoteric or odd, but
are functions you encounter every day.
 

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,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top