210 likes | 330 Views
System Programming in C. Lecture 11. Lecture Summary. Complete binary trees Variable number of arguments Passing structure by value Makefiles System calls More library functions…. Variable Number of Arguments. How does printf work ? printf(const char *format, ...)
E N D
System Programming in C Lecture 11
Lecture Summary • Complete binary trees • Variable number of arguments • Passing structure by value • Makefiles • System calls • More library functions…
Variable Number of Arguments How does printf work ? printf(const char *format, ...) 0 or more arguments can be used instead of ellipses (...) The first parameter must be explicit, so ... can appear only at the end of argument list. When function is being called at run time, the number and type of arguments being passed must be somehow known to the calling function. In printf, the format string holds this information How to reference unnamed arguments? Functions in <stdargs.h> - va_start: function to init access to arguments - va_arg: function to access individual arguments - va_end: function for clean up
Variable Number of Arguments - Example #include <stdarg.h> int sum (int argcnt, ...) /* argcnt is num of args */ { va_list ap; /* argument pointer (macro) */ int ans = 0; va_start(ap, argcnt); /* init ap */ while (argcnt-- >0) /* process all args */ ans += va_arg(ap, int); va_end(ap); /* clean up */ return(ans); } Usage: int total = sum(5,85,90,97,79,96);
Variable Number of Arguments - Implementation typedef char * va_list; #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define va_end(ap) ( ap = (va_list)0 )
Passing Structure by Value #include <stdio.h> typedef struct fraction { int number; int denom; }FRACTION; void InitFraction1(FRACTION *frac, int n, int d) { frac->number = n; /* receives structure by reference */ frac->denom = d; } void InitFraction2(FRACTION frac, int n, int d) { frac.number = n; /* receives structure by value */ frac.denom = d; }
Passing Structure by Value int main(int argc, char **argv) { FRACTION f1; InitFraction1(&f1,1,2); printf("%d, %d\n", f1.number, f1.denom); InitFraction2(f1,3,4); printf("%d, %d\n", f1.number, f1.denom); } Output?
Makefiles • So far program building/etc. was performed using Visual Studio IDE. .DSW/.DSP files were used to store project information. • An alternative to IDE - Microsoft NMAKE utility performs program maintenance tasks according to instructions it encounters in makefile. • Unix MAKE utility – does same sort of things. • Structure of makefile target: zero or more components command1 command2 …
Makefiles Running NMAKE makes it process makefile in current directory dependency rules list.exe : main.obj list.obj link /OUT:list.exe main.obj list.obj main.obj : main.c list.h cl /c main.c list.obj : list.c list.h cl /c list.c default dependencies list.exe : main.obj list.obj link /OUT:list.exe main.obj list.obj list.obj : list.h
Makefiles - Macros Macro – shorthand used in makefile NAME = value Example: CC = CL.EXE LINK = LINK.EXE Using a macro: $(LINK) Example: list.exe : $(OBJS) $(LINK) /OUT:$@ $(OBJS) Example makefile: LINK = LINK.EXE OBJS = list.obj main.obj list.exe : $(OBJS) $(LINK) /OUT:$@ $(OBJS)
Makefiles multiple targets LINK = LINK.EXE OBJS = list.obj main.obj all: list.exe test.exe list.exe : $(OBJS) $(LINK) /OUT:$@ $(OBJS) test.exe : test.obj $(LINK) /OUT:$@ test.obj
Makefiles – Multiple Maintanance Actions - The make command will perform the first task in the makefile (in previous example – all:) - Additional maintenance tasks may be specified: LINK = LINK.EXE OBJS = list.obj main.obj list.exe : $(OBJS) $(LINK) /OUT:$@ $(OBJS) rebuild: clean list.exe test: list.exe -del out.txt -list.exe > out.txt clean: -del *.obj -del *.exe -del out.txt
Makefiles – Multiple Maintenance Actions Usage: NMAKE clean NMAKE rebuild NMAKE test NMAKE Source for more information: - on Microsoft NMAKE: MSDN article “Overview: NMAKE Reference” - on other vendor’s MAKE utility – in appropriate documentation
System Calls List of system calls (system-dependent) int _open( const char *filename, int oflag [, int pmode] ); int _close( int handle ); int _read( int handle, void *buffer, unsigned int count ); int _write( int handle, const void *buffer, unsigned int count ); long _lseek( int handle, long offset, int origin ); long _tell( int handle ); int _eof( int handle ); int _commit( int handle ); These functions invoke the operating system directly for lower-level operation than that provided by stream I/O. Low-level input and output calls do not buffer or format data. Low-level I/O routines set the errno global variable when an error occurs. Reside in IO.H (For MSVC, may reside in another files for other implementations
System Calls: _tell example /* TELL.C: This program uses _tell to tell thefile pointer position after a file read. */ #include <io.h> #include <stdio.h> #include <fcntl.h> void main( void ) { int fh; char buffer[500]; if( (fh = _open( "tell.c", _O_RDONLY )) != -1 ) { if( _read( fh, buffer, 500 ) > 0 ) printf( "Current file position is: %d\n", _tell( fh ) ); _close( fh ); } } Output: Current file position is: 434
System Calls - _commit example #include <io.h> #include <stdio.h> #include <fcntl.h> #include <memory.h> #include <errno.h> #define MAXBUF 32 int log_receivable( int ); void main( void ) { int fhandle; fhandle = _open( "TRANSACT.LOG", _O_APPEND | _O_CREAT | _O_BINARY | _O_RDWR ); log_receivable( fhandle ); _close( fhandle ); }
System Calls - _commit example int log_receivable( int fhandle ) { /* The log_receivable function prompts for a name and a monetary * amount and places both values into a buffer (buf). The _write * function writes the values to the operating system and the * _commit function ensures that they are written to a disk file. */ int i; char buf[MAXBUF]; memset( buf, '\0', MAXBUF ); /* Begin Transaction. */ printf( "Enter name: " ); gets( buf ); …
System Calls - _commit example … for( i = 1; buf[i] != '\0'; i++ ); /* Write the value as a '\0' terminated string. */ _write( fhandle, buf, i+1 ); printf( "\n" ); memset( buf, '\0', MAXBUF ); printf( "Enter amount: $" ); gets( buf ); for( i = 1; buf[i] != '\0'; i++ ); /* Write the value as a '\0' terminated string. */ _write( fhandle, buf, i+1 ); printf( "\n" ); /* The _commit function ensures that two important pieces of * data are safely written to disk. The return value of the * _commit function is returned to the calling function. */ return _commit( fhandle ); }
Search & Sort library functions void *bsearch( const void *key, const void *base, size_t num, size_t width, int ( __cdecl *compare ) ( const void *elem1, const void *elem2 ) ); void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
Example on _bsearch & _qsort /* QSORT.C: This program reads the command-line parameters and uses qsort to sort them. It then displays the sorted arguments. */ #include <stdlib.h> #include <string.h> #include <stdio.h> int compare( const void *arg1, const void *arg2 ); void main( int argc, char **argv ) { int i; /* Eliminate argv[0] from sort: */ argv++; argc--; /* Sort remaining args using Quicksort algorithm: */ qsort( (void *)argv, (size_t)argc, sizeof( char * ), compare ); /* Output sorted list: */ for( i = 0; i < argc; ++i ) printf( "%s ", argv[i] ); printf( "\n" ); }
Example on _bsearch & _qsort int compare( const void *arg1, const void *arg2 ) { /* Compare all of both strings: */ return _stricmp( * ( char** ) arg1, * ( char** ) arg2 ); }