Submitted by Anonymous (not verified) on Sun, 03/10/2013 - 01:20

Prototyping Functions

In the following subsections, we're going to study three cases regarding arguments passed to functions. The first case is a function that takes no argument; the second one is a function that takes a fixed number of arguments; the third case is a function that takes a variable number of arguments.
Functions with No Arguments

The first case is a function that takes no argument. For instance, the C library function getchar() does not need any arguments. It can be used in a program like this:

int c;
c = getchar();

As you can see, the second statement is left blank between the parentheses (( and )) when the function is called.

In C, the declaration of the getchar() function can be something like this:

int getchar(void);

Note that the keyword void is used in the declaration to indicate to the compiler that no argument is needed by this function. The compiler will issue an error message if somehow there is an argument passed to getchar() later in a program when this function is called.

Therefore, for a function with no argument, the void data type is used as the prototype in the function declaration.

The program in Listing 5.2 gives another example of using void in function declarations.
 

TYPE
Listing 15.2. Using void in function declarations.


1:  /* 15L02.c: Functions with no arguments */
2:  #include <stdio.h>
3:  #include <time.h>
4:
5:  void GetDateTime(void);
6:
7:  main()
8:  {
9:     printf("Before the GetDateTime() function is called.\n");
10:    GetDateTime();
11:    printf("After the GetDateTime() function is called.\n");
12:    return 0;
13: }
14: /* GetDateTime() definition */
15: void GetDateTime(void)
16: {
17:    time_t now;
18:
19:    printf("Within GetDateTime().\n");
20:    time(&now);
21:    printf("Current date and time is: %s\n",
22:       asctime(localtime(&now)));
23: }


OUTPUT

I obtain the following output after I run the executable, 15L02.exe, of the program in Listing 15.2 from a DOS prompt:

ANALISYS

C:\app>15L02
Before the GetDateTime() function is called.
Within GetDateTime().
Current date and time is: Sat Apr 05 11:50:10 1997
After the GetDateTime() function is called.
C:\app>

The purpose of the program in Listing 15.2 is to give you the current date and time on your computer by calling the function GetDateTime(), declared in line 5. Because no argument needs to be passed to the function, the void data type is used as the prototype in the declaration of GetDateTime().

Additionally, another void keyword is used in front of the name of the GetDateTime() function to indicate that this function doesn't return any value either. (See line 5.)

The statements in lines 9 and 11 print out messages respectively before and after the GetDateTime() function is called from within the main() function.

In line 10, the function is called by the statement GetDateTime();. Note that no argument should be passed to this function, because the function prototype is void.

The definition of GetDateTime() is in lines 15_23; it obtains the calendar time and converts it into a character string by calling several C library functions, such as time(), localtime(), and asctime(). Then, the character string containing the information of current date and time is printed out on the screen by the printf() function with the format specifier %s. As you can see, the output on my screen shows that at the moment the executable 15L02.exe is being executed, the date and time are

Sat Apr 05 11:50:10 1997

time(), localtime(), and asctime() are date and time functions provided by the C language. These functions are discussed in the following subsection. You might notice that the header file time.h is included at the beginning of the program in Listing 15.2 before these time functions can be used.

Using time(), localtime(), and asctime()

Several C functions are called date and time functions. The declarations of all date and time functions are included in the header file time.h. These functions can give three types of date and time:

    Calendar time
    Local time
    Daylight savings time

Here calendar time gives the current date and time based on the Gregorian calendar. Local time represents the calendar time in a specific time zone. Daylight savings time is the local time under the daylight savings rule.

In this section, three date and time functions—time(), localtime(), and asctime()—are briefly introduced.

In C, the time() function returns the calendar time.

The syntax for the time() function is

#include <time.h>
time_t time(time_t *timer);

Here time_t is the arithmetic type that is used to represent time. timer is a pointer variable pointing to a memory storage that can hold the calendar time returned by this function. The time() function returns -1 if the calendar time is not available on the computer.

The localtime()function returns the local time converted from the calendar time.

The syntax for the localtime() function is

#include <time.h>
struct tm *localtime(const time_t *timer);

Here tm is a structure that contains the components of the calendar time. struct is the keyword for structure, which is another data type in C. (The concept of structures is introduced in Hour 19, "Collecting Data Items of Different Types.") timer is a pointer variable pointing to a memory storage that holds the calendar time returned by the time() function.

To convert the date and time represented by the structure tm, you can call the asctime() function.

The syntax for the asctime() function is

#include <time.h>
char *asctime(const struct tm *timeptr);

Here timeptr is a pointer referencing the structure tm returned by date and time functions like localtime(). The asctime() function converts the date and time represented by tm into a character string.

In Listing 15.2, the statement in line 17 declares a time_t variable called now. Line 20 stores the calendar time into the memory location referenced by the now variable. Note that the argument passed to the time() function should be the left value of a variable; therefore, the address-of operator (&) is used prior to now. Then, the expression in line 22, asctime(localtime(&now)), obtains the local time expression of the calendar time by calling localtime(), and converts the local time into a character string with help from asctime(). The character string of the date and time is then printed out by the printf() function in lines 21 and 22, which has the following format:

Sat Apr 05 11:50:10 1997\n\0

Note that there is a newline character appended right before the null character in the character string that is converted and returned by the asctime() function.
Functions with a Fixed Number of Arguments

You have actually seen several examples that declare and call functions with a fixed number of arguments. For instance, in Listing 15.1, the declaration of the function_1() function in line 4

int function_1(int x, int y);

contains the prototype of two arguments, x and y.

To declare a function with a fixed number of arguments, you need to specify the data type of each argument. Also, it's recommended to indicate the argument names so that the compiler can have a check to make sure that the argument types and names declared in a function declaration match the implementation in the function definition.
Prototyping a Variable Number of Arguments

As you may still remember, the syntax of the printf() function is

int printf(const char *format[, argument, ...]);

Here the ellipsis token ... (that is, three dots) represents a variable number of arguments. In other words, besides the first argument that is a character string, the printf() function can take an unspecified number of additional arguments, as many as the compiler allows. The brackets ([ and ]) indicate that the unspecified arguments are optional.

The following is a general form to declare a function with a variable number of arguments:

data_type_specifier  function_name(
      data_type_specifier argument_name1, ...
);

Note that the first argument name is followed by the ellipsis (...) that represents the rest of unspecified arguments.

For instance, to declare the printf() function, you can have something like this:

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

Processing Variable Arguments

There are three routines, declared in the header file stdarg.h, that enable you to write functions that take a variable number of arguments. They are va_start(), va_arg(), and va_end().

Also included in stdarg.h is a data type, va_list, that defines an array type suitable for containing data items needed by va_start(), va_arg(), and va_end().

To initialize a given array that is needed by va_arg() and va_end(), you have to use the va_start() macro routine before any arguments are processed.

The syntax for the va_start() macro is

#include <stdarg.h>
void va_start(va_list ap, lastfix);

Here ap is the name of the array that is about to be initialized by the va_start() macro routine. lastfix should be the argument before the ellipsis (...) in the function declaration.

By using the va_arg()macro, you're able to deal with an expression that has the type and value of the next argument. In other words, the va_arg() macro can be used to get the next argument passed to the function.

The syntax for the va_arg() macro is

#include <stdarg.h>
type va_arg(va_list ap, data_type);

Here ap is the name of the array that is initialized by the va_arg() macro routine. data_type is the data type of the argument passed to function.

To facilitate a normal return from your function, you have to use the va_end() function in
your program after all arguments have been processed.

The syntax for the va_end() function is

#include <stdarg.h>
void va_end(va_list ap);

Here ap is the name of the array that is initialized by the va_end() macro routine.

Remember to include the header file, stdarg.h, in your program before you call va_start(), va_arg(), or va_end().

Listing 5.3 demonstrates how to use va_start(), va_arg(), and va_end() in a function that takes a variable number of arguments.

TYPE
Listing 15.3. Processing variable arguments.


1:  /* 15L03.c: Processing variable arguments */
2:  #include <stdio.h>
3:  #include <stdarg.h>
4:
5:  double AddDouble(int x, ...);
6:
7:  main ()
8:  {
9:     double d1 = 1.5;
10:    double d2 = 2.5;
11:    double d3 = 3.5;
12:    double d4 = 4.5;
13:
14:    printf("Given an argument: %2.1f\n", d1);
15:    printf("The result returned by AddDouble() is: %2.1f\n\n",
16:       AddDouble(1, d1));
17:    printf("Given arguments: %2.1f and %2.1f\n", d1, d2);
18:    printf("The result returned by AddDouble() is: %2.1f\n\n",
19:       AddDouble(2, d1, d2));
20:    printf("Given arguments: %2.1f, %2.1f and %2.1f\n", d1, d2, d3);
21:    printf("The result returned by AddDouble() is: %2.1f\n\n",
22:       AddDouble(3, d1, d2, d3));
23:    printf("Given arguments: %2.1f, %2.1f, %2.1f, and %2.1f\n", d1, d2, d3, Âd4);
24:    printf("The result returned by AddDouble() is: %2.1f\n",
25:       AddDouble(4, d1, d2, d3, d4));
26:    return 0;
27: }
28: /* definition of AddDouble() */
29: double AddDouble(int x, ...)
30: {
31:    va_list   arglist;
32:    int i;
33:    double result = 0.0;
34:
35:    printf("The number of arguments is: %d\n", x);
36:    va_start (arglist, x);
37:    for (i=0; i<x; i++)
38:       result += va_arg(arglist, double);
39:    va_end (arglist);
40:    return result;
41: }


OUTPUT

The following output is displayed on the screen after the executable, 15L03.exe, is run from a DOS prompt:

C:\app>15L03
Given an argument: 1.5
The number of arguments is: 1
The result returned by AddDouble() is: 1.5

Given arguments: 1.5 and 2.5
The number of arguments is: 2
The result returned by AddDouble() is: 4.0

Given arguments: 1.5, 2.5, and 3.5
The number of arguments is: 3
The result returned by AddDouble() is: 7.5

Given arguments: 1.5, 2.5, 3.5, and 4.5
The number of arguments is: 4
The result returned by AddDouble() is: 12.0
C:\app>

ANALYSIS

The program in Listing 15.3 contains a function that can take a variable number of double arguments, perform the operation of addition on these arguments, and then return the result to the main() function.

The declaration in line 5 indicates to the compiler that the AddDouble() function takes a variable number of arguments. The first argument to AddDouble() is an integer variable that holds the number of the rest of the arguments passed to the function each time AddDouble() is called. In other words, the first argument indicates the number of remaining arguments to be processed.

The definition of AddDouble() is given in lines 29_41, in which a va_list array, arglist, is declared in line 31. As mentioned, the va_start() macro has to be called before the arguments are processed. Thus, line 36 invokes va_start() to initialize the array arglist. The for loop in lines

37 and 38 fetches the next double argument saved in the array arglist by calling va_arg(). Then, each argument is added into a local double variable called result.

The va_end() function is called in line 39 after all arguments saved in arglist have been fetched

and processed. Then, the value of result is returned back to the caller of the AddDouble() function, which is the main() function in this case.

The va_end() function has to be called in a C program to end variable argument processing. Otherwise, the behavior of the program is undefined.

As you can see, within the main() function, AddDouble() is called four times, with a different number of arguments each time. These arguments passed to AddDouble() are displayed by the printf() functions in lines 14, 17, 20, and 23. Also, the four different results returned by AddDouble() are printed out on the screen.

Related Items

মডুলার C প্রোগ্রামিং (Modular C Programming)

কেবল মাত্র একটি ফাংশন দিয়ে কোনো বড়ো জটিল সমস্যা সমাধানের চেষ্টা করা ভাল প্রোগ্রামিংয়ের পদ্ধতি নয়। সঠিক পদ্ধতি হ'ল সমস্যাটিকে কয়েকটি ছোট ছোট এবং সরল টুকরো করে ফেলা যাতে তা আরও বিশদে বোঝা যায় । তারপরে এই ছোট এবং সরল সমস্যাগুলি সমাধান করার জন্য ছোট ছোট ফাংশন ব্লক তৈরি করা এবং পরে সেগুলি নিয়মানুযায়ী সংযোজিত করা ।

Programming Style

Programming Style

In this section, I'd like to briefly highlight some points that will help you write clean programs that can easily be read, understood, and maintained.

Exercises : Answer the following Question

To help solidify your understanding of this hour's lesson, you are encouraged to answer the quiz questions and finish the exercises provided in the Workshop before you move to the next lesson.

Question and Answer

    Q Is the C preprocessor part of the C compiler?

    A No. The C preprocessor is not part of the C compiler. With its own line-oriented grammar and syntax, the C preprocessor runs before the compiler in order to handle named constants, macros, and inclusion of files.

Compiling Your Code Under Conditions

Compiling Your Code Under Conditions

You can select portions of your C program that you want to compile by using a set of preprocessor directives. This is useful, especially when you're testing a piece of new code or debugging a portion of code.