Book
Collection
Click for Table of Contents
© 2025 by Rance D. Necaise
C Primer for Python Programmers
Copyright © 2025
Rance D. Necaise

9.4 Struct Parameters

In C, structures can be passed as arguments to a function and returned as a value from a function. When a struct variable is passed to a function, the entire contents is copied from the source argument to the destination parameter. Consider the Point structure from Section 9.1

  1. struct Point {
  2.   int x;
  3.   int y;
  4. };

and the following function definition

  1.  // Determines in which quadrant a point lies, which is a value in the range [1..4].
  2. int quandrant(struct Point pt)
  3. {
  4.   if(pt.x >= 0 && pt.y >= 0)
  5.     return 1;
  6.   else if(pt.x < 0 && pt.y >= 0)
  7.     return 2;
  8.   else if(pt.x < 0 && pt.y < 0)
  9.     return 3;
  10.   else
  11.     return 4;
  12. }

Pass By Value

We can pass a Point struct variable to the function, in the same fashion that we would with an integer or floating-point value:

  1. struct Point start = {.x = 4, .y = 4};
  2. struct Point stop = {.x = 5, .y = -7};
  3.  
  4. int quad = quadrant(start);

When the function is called, the entire contents of the start struct variable is passed to the function and assigned to the pt argument:

Pass By Reference

When a function needs to modify the contents of a struct, a pointer to the struct can be passed instead of the actual struct variable itself. Suppose we have a function that can shift a point by a given amount in the x and y direction:

  1. void shiftPoint(struct Point *pt, int shiftX, int shiftY)
  2. {
  3.   pt->x = pt->x + shiftX;
  4.   pt->y = pt->y + shiftY;
  5. }

We can call the function and pass the address of one of our points to the function

  1. shiftPoint(&stop, 3, 4);

When the function is called, only the address of stop is passed to the function

As the body of the function executes, it dereferences the pointer to modify the fields of the stop struct variable, which results in

Tip
Tip

Passing a Constant Pointer

While it is convenient to pass structures to functions by value, it can be inefficient to pass large structs. Instead, it is better to design the function to accept a constant pointer and pass the address to the function. For example, consider the Address struct from Section 9.2. If we need to pass an Address struct variable to a function that does not need to change the value of any of the fields, we can design a function to accept a constant pointer to the struct,

  1. void printAddress(const struct Address *record)
  2. {
  3.   ...
  4. }

We would call the function by passing the address of the struct variable to the function

  1. printAddress(&whiteHouse);

The only difference is that the function can not modify the contents of the pointer to the struct variable. If a statement is included in the function that attempts to modify the struct variable, a syntax error would be flagged. This is also an easy way to ensure that a function does not accidentally modify a "read only" variable.

Returning a Struct

Now, suppose we want to design and implement a function that can read the coordinates of a point from the user and return those in a Point structure. Unlike arrays, a function in C can return a struct variable. Consider the readPoint function below:

  1.  // Prompts for and reads a 2-D coordinate from the user.
  2. struct Point readPoint()
  3. {
  4.   struct Point pt;
  5.  
  6.   printf("Enter the x-coordinate: ");
  7.   scanf("%d", &pt.x);
  8.   printf("Enter the y-coordinate: ");
  9.   scanf("%d", &pt.y);
  10.  
  11.   return pt;
  12. }

We can call the function to prompt the user and read the two coordinates

  1. struct Point middle;
  2. middle = readPoint();

Suppose the user enters 12 for the x-coordinate and 8 for the y-coordinate. The values are stored in the local Point struct pt, as illustrated below,

When the function returns, the entire contents of the local struct variable pt is copied to the middle struct variable, byte by byte, the same as if you had assigned it directly

Question 9.4.1

Complete the implementation of the printAddress function defined above in the Tip box above.

  1. void printAddress(const struct Address *record)
  2. {
  3.   printf("%d %s\n", record->number, record->street);
  4.   printf("%s, %s  %d\n", record->state, record->zipcode);
  5. }
Question 9.4.2

Define a function prototype with the name isEqual that accepts two Card structures (as defined in Section 9.1) and returns a Boolean indicating whether the two cards are identical.

  1. bool isEqual(struct Card card1, struct Card card2);
Question 9.4.3

Implement the isEqual function that you defined in the previous question.

  1. bool isEqual(struct Card card1, struct Card card2)
  2. {
  3.   return card1.suit == card2.suit && card1.value == card2.value;
  4. }