How to Return a Struct From Function in C

Jinku Hu Feb 02, 2024
  1. Use Standard Notation to Return a Struct From a Function in C
  2. Use Pointer Notation to Return a Struct From a Function in C
  3. Return a Struct by Value in C
  4. Return a Struct via malloc in C
  5. Return a Struct via a Global Variable in C
  6. Conclusion
How to Return a Struct From Function in C

In C programming, structures (or structs) allow you to group different data types under a single name, making it a powerful tool for organizing and managing data.

One common requirement is the need to return a struct from a function, allowing for the creation of modular and reusable code. This article will demonstrate multiple methods about how to return a struct from a function in C, along with detailed examples for each method.

Use Standard Notation to Return a Struct From a Function in C

The struct keyword in C is used to implement user-defined data structures. Since we define the struct type in this example, it will be a cleaner notation for function declarations if we typedef the MyStruct structure.

It will associate a new type alias for the given structure, and we’d need to specify only the new alias name in the function prototype. Now, functions in C can return the struct similar to the built-in data types.

In the following example code, we implemented a clearMyStruct function that takes a pointer to the MyStruct object and returns the same object by value. Note that we need to access struct members using the -> operator when the handle is the pointer to the struct.

#include <stdio.h>
#include <stdlib.h>

enum { DAY = 9, MONTH = 2 };

typedef struct {
  int day;
  int month;
} MyStruct;

MyStruct clearMyStruct(MyStruct *st) {
  st->day = 0;
  st->month = 0;

  return *st;
}

int setMyStruct(MyStruct *st, int d, int m) {
  if (!st) return -1;
  st->day = d;
  st->month = m;
  return 0;
}

int main() {
  MyStruct tmp;

  if (setMyStruct(&tmp, DAY, MONTH) == -1) exit(EXIT_FAILURE);

  printf("day: %d\nmonth: %d\n", tmp.day, tmp.month);
  clearMyStruct(&tmp);
  printf("day: %d\nmonth: %d\n", tmp.day, tmp.month);

  exit(EXIT_SUCCESS);
}

This code defines a structure MyStruct with integer members day and month. It also includes functions to manipulate this structure.

The clearMyStruct function sets both day and month to 0 and returns the modified structure. The setMyStruct function updates the day and month members with provided values, returning 0 on success or -1 if the pointer is invalid.

In main(), a MyStruct variable tmp is created. setMyStruct is called with arguments &tmp, DAY, and MONTH. If an error occurs, the program exits with a failure status.

The program then prints day and month. clearMyStruct is called to reset the values, which are then printed again.

The program exits with a success status.

Output:

day: 9
month: 2
day: 0
month: 0

Use Pointer Notation to Return a Struct From a Function in C

Generally, struct defined data structures tend to contain multiple data members, resulting in a big memory footprint. Now, when it comes to passing relatively big structures between functions, it’s best to use pointers.

The pointer serves as a handle to the object, and its size is fixed regardless of the structure stored there. Using pointers to return struct potentially reduces memory traffic and gives code more performance.

Although the program is compiled with optimization flags, it may implicitly modify the data-passing instructions. Note that we utilized the enum type to declare named constant integer values.

Example:

#include <stdio.h>
#include <stdlib.h>

enum { DAY = 9, MONTH = 2 };

typedef struct {
  int day;
  int month;
} MyStruct;

MyStruct *clearMyStruct2(MyStruct *st) {
  st->day = 0;
  st->month = 0;

  return st;
}

int setMyStruct(MyStruct *st, int d, int m) {
  if (!st) return -1;
  st->day = d;
  st->month = m;
  return 0;
}

int main() {
  MyStruct tmp;

  if (setMyStruct(&tmp, DAY, MONTH) == -1) exit(EXIT_FAILURE);

  printf("day: %d\nmonth: %d\n", tmp.day, tmp.month);
  clearMyStruct2(&tmp);
  printf("day: %d\nmonth: %d\n", tmp.day, tmp.month);

  exit(EXIT_SUCCESS);
}

This code defines a structure MyStruct with two integer members: day and month. It also includes two functions.

The setMyStruct function takes a pointer to a MyStruct (st) along with integer values for day and month. It checks if the pointer is valid and then assigns the provided values to the struct’s members. If successful, it returns 0; otherwise, it returns -1.

The clearMyStruct2 function takes a pointer to a MyStruct (st) and sets both day and month to 0. It then returns the same pointer.

In main, a local MyStruct variable called tmp is created. The setMyStruct function is called to set its day to 9 and month to 2.

If the operation fails (due to a null pointer), the program exits with a failure status. The values are then printed.

Next, clearMyStruct2 is called with a pointer to tmp. This sets both day and month to 0.

The updated values are then printed. Finally, the program exits with a success status.

Output:

day: 9
month: 2
day: 0
month: 0

Return a Struct by Value in C

Returning a struct by value means that a function generates a copy of the entire struct and passes it back to the caller. This approach is straightforward and effective for small or moderately sized structs.

In the example below, the function returnStructByValue returns a struct directly. This works well for small structs, but it can be inefficient for larger ones due to the memory overhead associated with copying the entire struct.

#include <stdio.h>

// Define a simple struct
struct Point {
  int x;
  int y;
};

// Function to return a struct by value
struct Point returnStructByValue() {
  struct Point p = {3, 4};
  return p;
}

int main() {
  struct Point result = returnStructByValue();
  printf("Result: (%d, %d)\n", result.x, result.y);
  return 0;
}

This code begins by including the standard input/output library (stdio.h). Then, a simple struct named Point is defined, consisting of two integer members: x and y.

Following this, a function named returnStructByValue is declared. This function returns a struct Point by value.

Inside the function, a local variable p of type struct Point is created and initialized with the values 3 and 4. The function then returns this struct using the return statement.

In the main function, a variable named result of type struct Point is declared. The returnStructByValue function is called, and the returned struct is assigned to result.

Finally, the values of result.x and result.y are printed using printf.

Output:

Result: (3, 4)

It is worth noting that for larger or more complex structs, alternative methods like returning via pointers or dynamic memory allocation may be more appropriate to ensure efficient memory usage.

Return a Struct via malloc in C

malloc stands for “memory allocation”. It is a standard C library function that allows you to dynamically allocate memory at runtime.

This means you can request memory as your program runs and free it when it’s no longer needed.

The malloc function returns a pointer to the allocated memory block, which you can use to store data. It’s a fundamental tool for managing memory efficiently in C programs.

Syntax:

void* malloc(size_t size);

Here, size is the number of bytes to allocate. It returns a pointer to the allocated memory or NULL if the allocation fails.

In the example below, the function returnStructViaMalloc dynamically allocates memory for a struct using malloc. It then sets the values and returns a pointer to the allocated memory.

This approach is useful when you want to return a dynamically allocated struct, but don’t forget to free the memory after use.

#include <stdio.h>
#include <stdlib.h>

// Define a simple struct
struct Point {
  int x;
  int y;
};

// Function to dynamically allocate and return a struct
struct Point* returnStructViaMalloc() {
  struct Point* p = (struct Point*)malloc(sizeof(struct Point));
  if (p != NULL) {
    p->x = 3;
    p->y = 4;
  }
  return p;
}

int main() {
  struct Point* result = returnStructViaMalloc();
  if (result != NULL) {
    printf("Result: (%d, %d)\n", result->x, result->y);
    free(result);  // Don't forget to free the memory!
  }
  return 0;
}

In this code, a struct named Point is defined, which contains two integer members: x and y.

Next, there is a function called returnStructViaMalloc, which returns a pointer to a Point struct. Within this function, memory is dynamically allocated using malloc to create space for a Point struct.

If the allocation is successful (p is not NULL), the values of x and y are assigned as 3 and 4, respectively. Finally, the pointer p is returned.

In the main function, a pointer named result is declared. It is assigned the value returned by returnStructViaMalloc(), which is a dynamically allocated Point struct.

Next, there is a check to ensure that the allocation was successful (result is not NULL). If so, the values of x and y are printed using printf.

Finally, it is crucial to free the allocated memory using free(result) to prevent memory leaks.

Output:

Result: (3, 4)

This is an effective way to allocate memory for a struct dynamically and return it from a function while also emphasizing the importance of memory deallocation using free().

Return a Struct via a Global Variable in C

In this method, we use a global variable globalResult to store the result. The function returnStructViaGlobal modifies this global variable.

While this approach is simple, it can lead to problems in larger programs due to potential conflicts with other parts of the code.

#include <stdio.h>

// Define a simple struct
struct Point {
  int x;
  int y;
};

// Define a global variable to store the result
struct Point globalResult;

// Function to modify the global variable
void returnStructViaGlobal() {
  globalResult.x = 3;
  globalResult.y = 4;
}

int main() {
  returnStructViaGlobal();
  printf("Result: (%d, %d)\n", globalResult.x, globalResult.y);
  return 0;
}

In this code, a struct named Point is defined, containing two integer members: x and y.

Following this, a global variable globalResult of type Point is declared. This variable will store the result of the function operation.

Next, a function named returnStructViaGlobal is defined. Within this function, the x member of globalResult is assigned the value 3, and the y member is assigned the value 4.

Moving on to the main function, returnStructViaGlobal() is called, which updates the values of globalResult. Finally, a printf statement is used to display the values of x and y stored in globalResult.

Output:

Result: (3, 4)

This approach is relatively straightforward, but it’s important to be cautious when using global variables as they can lead to potential conflicts and make the code less modular.

Conclusion

Structures in C provide a powerful way to organize data. This article explored multiple methods for returning a struct from a function.

  • Standard Notation: Using typedef with structs improves code readability and allows functions to return structs like built-in types.
  • Efficient Memory Management: For large data structures, using pointers can enhance performance. Functions can directly modify struct members through pointers.
  • Returning by Value: This method involves creating a copy of the entire struct within a function and passing it back to the caller. It’s efficient for small to moderately sized structs.
  • Dynamic Memory Allocation with malloc: This allows you to allocate memory for a struct at runtime. Remember to free the memory after use to prevent memory leaks.
  • Global Variables: While simple, using global variables can lead to potential conflicts and reduce modularity, especially in larger programs. It may be suitable for smaller, well-defined scopes.

By choosing the right method based on your specific needs, you can write more efficient and maintainable C programs.

Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Related Article - C Struct