/* ** $Id: functions.c 733 2008-02-08 23:54:26Z phf $ ** ** Just some random functions to explain the basics. */ #include #include // a real global variable, just to illustrate, try not // to have too many of these... int ein_kleiner_global = 42; int negate( int x ) { return -x; } int square( int x ) { // this just illustrates what "static" means inside // a function; it's really a "global" variable, so // it is alive for the whole program run, but we // can only access it inside the function we put it // in; it's a "fake" global? you shouldn't really // ever need it, unless you need to count how often // a function got called, which is what we do here. static int count = 0; // only set to zero initially! count += 1; printf("Called square() %d times so far! [%d]\n", count, ein_kleiner_global); // this is the actual squaring part return x*x; } int negandsqr( int x ) { return square( negate( x ) ); // call functions inside functions } void greet( const char *name ) // const promises we won't change the string { printf( "Live long and prosper, %s!\n", name ); } void hello() // empty parameter list (see main() below) { printf( "Hello" ); } void world( void ) // void parameter list (see main() below) { printf( "World" ); } // Recursive functions are allowed, but nobody computes n! this // way, it's nuts... (http://www.luschny.de/math/factorial/ has // lots of better ways) int fact( int n ) { if (n <= 1) { return 1; // base case } else { return n*fact( n-1 ); // recursive call (inductive case) } } // Slightly better, at least we're not carrying around all those // useless stack frames anymore... int better_fact( int n ) { int result = 1; for (int i = 1; i <= n; i++) { result *= i; } return result; } // This is a prototype: We're telling the compiler "Trust me, // you will see a function of this type later." and it does. // You may need this for mutually recursive functions; some // languages call this a "forward declaration" since the // code comes later in the program text. If you don't have a // prototype but call a function anyway, the compiler will // make up a type for you, usually not what you want. void after_main( void ); // Here's the main() function, the thing that gets called // first (well, almost first) when you run the program. int main( void ) { int i; // Hello World! split into functions (not exactly // useful of course) hello(); printf( " " ); world(); printf( "!\n" ); // A function with a string parameter, not too // helpful either. greet( "Peter" ); greet( "W" ); // Something slightly more complicated, including // calling functions to fill arguments for other // functions; we discussed "evaluation order" here // in lecture. for (i = 0; i < 10; i++) { printf( "The square of %d is %d!\n", negate( i ), square( negate( i ) ) ); } // And another one... :-) for (i = 0; i < 10; i++) { printf( "Factorial of %d is %d yep %d!\n", i, fact( i ), better_fact( i ) ); } // Return values are not taken too seriously in C, // for example: negate( 10 ); // This works fine, the returned value is simply // tossed away; I don't like it, neither should // you... :-) // Here's a weird thing: For hello() we used an empty // parameter list to indicate that it doesn't take a // parameter. However, that's not what C understands. // If you use an empty parameter list, which has been // around since the stone age, you get 1970s behavior: // Calls of that function are *not* checked in regard // to their parameter lists. Oh the horror: hello(); printf( " " ); hello( 10, 20 ); printf( " " ); hello( hello ); // extra weirdness!!! printf( "\n" ); // However, for world() we used a (void) parameter list, // so this one will be checked when we call the function. // Remove the comments below to see the error messages: world(); // world( 10, 20 ); // world( world ); printf( "\n" ); // Lesson: Don't make the mistake I made, always use the // (void) form to make sure you get all the checking you // deserve from the compiler! // Here's the call to the function we actually give code // for after the main() function. after_main(); return EXIT_SUCCESS; } // And here's the function whose prototype you saw just // before main() above. void after_main( void ) { puts( "I am declared after main()!" ); }