Structures and Function Calls
The C language allows you to pass an entire structure to a function. In addition, a function can return a structure back to its caller.
To show you how to pass a structure to a function, I rewrite the program in Listing 19.1 and create a function called DataReceive() in the program. The upgraded program is shown in Listing 19.3.
TYPE
Listing 19.3. Passing a structure to a function.1: /* 19L03.c Passing a structure to a function */
2: #include <stdio.h>
3:
4: struct computer {
5: float cost;
6: int year;
7: int cpu_speed;
8: char cpu_type[16];
9: };
10: /* create synonym */
11: typedef struct computer SC;
12: /* function declaration */
13: SC DataReceive(SC s);
14:
15: main(void)
16: {
17: SC model;
18:
19: model = DataReceive(model);
20: printf("Here are what you entered:\n");
21: printf("Year: %d\n", model.year);
22: printf("Cost: $%6.2f\n", model.cost);
23: printf("CPU type: %s\n", model.cpu_type);
24: printf("CPU speed: %d MHz\n", model.cpu_speed);
25:
26: return 0;
27: }
28: /* function definition */
29: SC DataReceive(SC s)
30: {
31: printf("The type of the CPU inside your computer?\n");
32: gets(s.cpu_type);
33: printf("The speed(MHz) of the CPU?\n");
34: scanf("%d", &s.cpu_speed);
35: printf("The year your computer was made?\n");
36: scanf("%d", &s.year);
37: printf("How much you paid for the computer?\n");
38: scanf("%f", &s.cost);
39: return s;
40: }
After I run the executable, 19L03.exe, and enter my answers to the questions, I get the following output, which is the same as the output from the executable program of List-
ing 19.1:
OUTPUT
C:\app>19L03
The type of the CPU inside your computer?
Pentium
The speed(MHz) of the CPU?
100
The year your computer was made?
1996
How much you paid for the computer?
1234.56
Here are what you entered:
Year: 1996
Cost: $1234.56
CPU type: Pentium
CPU speed: 100 MHz
C:\app>
ANALYSIS
The purpose of the program in Listing 19.3 is to show you how to pass a structure to a function. The structure in Listing 19.3, with the tag name of computer, is declared in lines 4_9.
Note that in line 11 the typedef keyword is used to define a synonym, SC, for structure computer. Then SC is used in the sequential declarations.
The DataReceive() function is declared in line 13, with the structure of computer as its argument (that is, the synonym SC and the variable name s), so that a copy of the structure can be passed to the function.
In addition, the DataReceive() function returns the copy of the structure back to the caller after the content of the structure is updated. To do this, SC is prefixed to the function in line 13 to indicate the data type of the value returned by the function.
The statement in line 17 defines the structure model with SC. The DataReceive() function is passed with the name of the model structure in line 19, and then the value returned by the function is assigned back to model as well. Note that if the DataReceive() function return value is not assigned to model, the changes made to s in the function will not be evident in model.
The definition of the DataReceive() function is shown in lines 29_40, from which you can see that the new data values entered by the user are saved into the corresponding members of the structure that is passed to the function. At the end of the function, the copy of the updated structure is returned in line 39.
Then, back to the main() function of the program, lines 21_24 print out the updated contents held by the members of the structure. Because the program in Listing 19.3 is basically the same as the one in Listing 19.1, I see the same output on my screen after running the executable file, 19L03.exe.
Pointing to Structures
As you can pass a function with a pointer that refers to an array, you can also pass a function with a pointer that points to a structure.
However, unlike passing a structure to a function, which sends an entire copy of the structure to the function, passing a pointer of a structure to a function is simply passing the address that associates the structure to the function. The function can then use the address to access the structure members without duplicating the structure. Therefore, it's more efficient to pass a pointer of a structure, rather than the structure itself, to a function.
Accordingly, the program in Listing 19.3 can be rewritten to pass the DataReceive() function with a pointer that points to the structure. The rewritten program is shown in Listing 19.4.
TYPE
Listing 19.4. Passing a function with a pointer that points to a structure.1: /* 19L04.c Pointing to a structure */
2: #include <stdio.h>
3:
4: struct computer {
5: float cost;
6: int year;
7: int cpu_speed;
8: char cpu_type[16];
9: };
10:
11: typedef struct computer SC;
12:
13: void DataReceive(SC *ptr_s);
14:
15: main(void)
16: {
17: SC model;
18:
19: DataReceive(&model);
20: printf("Here are what you entered:\n");
21: printf("Year: %d\n", model.year);
22: printf("Cost: $%6.2f\n", model.cost);
23: printf("CPU type: %s\n", model.cpu_type);
24: printf("CPU speed: %d MHz\n", model.cpu_speed);
25:
26: return 0;
27: }
28: /* function definition */
29: void DataReceive(SC *ptr_s)
30: {
31: printf("The type of the CPU inside your computer?\n");
32: gets((*ptr_s).cpu_type);
33: printf("The speed(MHz) of the CPU?\n");
34: scanf("%d", &(*ptr_s).cpu_speed);
35: printf("The year your computer was made?\n");
36: scanf("%d", &(*ptr_s).year);
37: printf("How much you paid for the computer?\n");
38: scanf("%f", &(*ptr_s).cost);
39: }
Similarly, I obtain output that is the same as the one from the program in Listing 19.3 after I run the executable (19L04.exe) of the program in Listing 19.4:
OUTPUT
C:\app>19L04
The type of the CPU inside your computer?
Pentium
The speed(MHz) of the CPU?
100
The year your computer was made?
1996
How much you paid for the computer?
1234.56
Here are what you entered:
Year: 1996
Cost: $1234.56
CPU type: Pentium
CPU speed: 100 MHz
C:\app>
ANALYSIS
The program in Listing 19.4 is almost identical to the one in Listing 19.3, except that the argument passed to the DataReceive() function is a pointer defined with SC—that is, structure computer. (Refer to lines 11 and 13.) Also, the DataReceive() function does not need to return a copy of the structure because the function can access all members of the original structure, not the copy, via the pointer passed to it. That's why the void keyword is prefixed to the function name in line 13.
The statement in line 17 defines the structure model. And in line 19, the address of the model structure is passed to the DataReceive function by applying the address-of operator (&).
When you look at the definition of the DataReceive() function in lines 29_39, you see that the dereferenced pointer *ptr_s is used to reference the members of the model structure. For instance, to access the char array of cpu_type, (*ptr_s) is used in the (*ptr_s).cpu_type expression to indicate to the compiler that cpu_type is a member in the structure pointed to by the pointer ptr_s. Note that the dereferenced pointer *ptr_s has to be enclosed within the parentheses (( and )).
Another example is the &(*ptr_s).cpu_speed expression in line 34, which leads to the address of the cpu_speed variable that is a member of the structure pointed to by the pointer ptr_s. Again, the dereferenced pointer *ptr_s is surrounded by the parentheses (( and )).
The next subsection shows you how to use the arrow operator (->) to refer to a structure member with a pointer.
Referencing a Structure Member with ->
You can use the arrow operator -> to refer to a structure member with a pointer that points to the structure.
For instance, you can rewrite the (*ptr_s).cpu_type expression in Listing 19.4 with this:
ptr_s -> cpu_type
or you could replace the &(*ptr_s).cpu_speed expression with this:
&(ptr_s->cpu_speed)
Because of its clearness, the -> operator is more frequently used in programs than the dot operator. Exercise 3, later in this hour, gives you a chance to rewrite the entire program in Listing 19.4 using the -> operator.
- 4 views