Unit 4 · Lesson 520 minAcademic review pending

Passing and returning structures

Unlike arrays, a structure is copied when passed. That makes it safe, lets a function return one whole value, and occasionally makes pointers worthwhile.

Choose explanation

After this lesson

You should be able to

  • Pass a structure to a function by value and by pointer.
  • Return a structure as a function's result.
  • Use the arrow operator to reach a member through a pointer.
01

Structures are copied; arrays are not

Passing a structure copies every member, so the function cannot change the caller's copy — exactly like an int, and unlike an array. That is worth pausing on, because it means a Student containing an array behaves differently from the array on its own.

For a large structure that copy costs time. Passing a pointer avoids it, and adding const keeps the safety you gave up: const Student *s says look but do not touch.

Same output, different cost
void show(Student s)          /* copy: safe, but copies everything */
{
    printf("%s scored %d\n", s.name, s.marks);
}

void show_fast(const Student *s)   /* no copy, still read-only */
{
    printf("%s scored %d\n", s->name, s->marks);
}
02

The arrow operator

When you hold a pointer to a structure, s->marks means the marks member of what s points at. It is shorthand for (*s).marks, and the parentheses in that longer form are compulsory because the dot binds tighter than the star.

So the rule is simple: dot for a structure, arrow for a pointer to one. Writing *s.marks is a common error and means something quite different.

03

Returning a whole structure

A function can return a structure by value, which is the clean way around return giving only one value — put the several answers in a structure and return that. No pointers, no output parameters.

Compare this with Unit II's divide function, which needed two pointer parameters. Returning a structure says the two results belong together, which the pointer version never states.

Two answers, one return
typedef struct {
    int quotient;
    int remainder;
} DivResult;

DivResult divide(int a, int b)
{
    DivResult r;
    r.quotient  = a / b;
    r.remainder = a % b;
    return r;              /* one value carrying two answers */
}

/* in main */
DivResult d = divide(17, 5);
printf("%d r %d\n", d.quotient, d.remainder);   /* 3 r 2 */

Try it yourself

Write a function that takes an array of Students and returns a structure holding both the topper and the class average.

Need a hint?

Define a second structure for the summary. It can contain a Student as a member.

Check the worked solution

Summary bundles two results that are meaningless apart, so returning one value is more honest than two output pointers. The array parameter is const because summarise only reads, while the returned Summary is a copy that stays valid after the function ends — a pointer to the local best would not.

#include <stdio.h>

typedef struct {
    int  roll;
    char name[40];
    int  marks;
} Student;

typedef struct {
    Student topper;
    double  average;
} Summary;

Summary summarise(const Student class[], int n)
{
    Summary out;
    int total = 0, best = 0;

    for (int i = 0; i < n; i++) {
        total += class[i].marks;
        if (class[i].marks > class[best].marks)
            best = i;
    }

    out.topper  = class[best];
    out.average = (double) total / n;
    return out;
}

int main(void)
{
    Student class[3] = {
        {101, "Kavya", 87}, {102, "Ravi", 64}, {103, "Sneha", 91}
    };
    Summary s = summarise(class, 3);

    printf("Topper %s with %d, average %.2f\n",
           s.topper.name, s.topper.marks, s.average);
    return 0;
}

Quick check

Given Student *p, how do you read the marks member?

Select an answer to check your thinking.

Why this lesson exists

Syllabus mapping

Structure Type Data as Input and Output Parameters · Functions with Structured Result Values

Maps to course outcomes CO4, CO5.