Intermediate · Structs, unions, enums and files · topic 32 of 60 · 25 min
Pointers to structs and the arrow operator
Explanation
The arrow operator
typedef struct { char name[30]; long balance_paise; } Account;
Account acc = {"Asha", 500000};
Account *p = &acc;
(*p).balance_paise += 10000; /* brackets needed: . binds tighter than * */
p->balance_paise += 10000; /* the same thing, the usual way to write it */
printf("%s: %ld\n", p->name, p->balance_paise); /* Asha: 520000 */Passing structs by pointer
void deposit(Account *a, long paise) { /* changes the caller's account */
if (paise > 0) a->balance_paise += paise;
}
void print_account(const Account *a) { /* read-only, no copy */
printf("%-10s Rs %.2f\n", a->name, a->balance_paise / 100.0);
}
deposit(&acc, 25000);
print_account(&acc);A struct with a 200-byte array would be copied on every by-value call. A pointer is 8 bytes. Mark it const when the function should not modify the struct; the compiler then rejects accidental writes.
Structs on the heap
Account *open_account(const char *name) {
Account *a = malloc(sizeof *a);
if (!a) return NULL;
snprintf(a->name, sizeof a->name, "%s", name);
a->balance_paise = 0;
return a;
}
Account *a = open_account("Ravi");
if (a) { deposit(a, 100000); print_account(a); free(a); }Nested structs
typedef struct { char city[20]; char pin[7]; } Address;
typedef struct { char name[30]; Address home; } Customer;
Customer c = { .name = "Meena", .home = { .city = "Kochi", .pin = "682001" } };
Customer *pc = &c;
printf("%s, %s\n", c.home.city, pc->home.pin); /* dot for the inner struct value */Self-referential structs
typedef struct Node {
int value;
struct Node *next; /* a pointer to another Node (a struct cannot contain itself, but can point to one) */
} Node;
Node third = {30, NULL};
Node second = {20, &third};
Node first = {10, &second};
for (Node *n = &first; n != NULL; n = n->next) printf("%d ", n->value); /* 10 20 30 */
first ──► [10 | ●] ──► [20 | ●] ──► [30 | NULL]Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Pointers to structs and the arrow operator · 1/6
In this lesson you will use pointers to structs.
Prefer a video by a teacher? Find free videos on “c pointer to struct arrow operator linked list node” on YouTube ↗
In real life: Updating a vehicle's FASTag balance
A toll-plaza simulator keeps each vehicle's tag as a struct. The function that charges a toll receives a pointer so it can reduce the caller's balance, and returns an error code if the balance is too low, without copying the struct.
typedef struct { char reg[12]; long balance_paise; } Tag;
int charge_toll(Tag *t, long toll_paise) {
if (!t || toll_paise <= 0) return -1;
if (t->balance_paise < toll_paise) return -2; /* insufficient balance */
t->balance_paise -= toll_paise;
return 0;
}Practice (0/3 done)
Given Account *p = &acc;, which is NOT equivalent to p->name?
The same idea in JavaScript, where objects are always passed by reference (like a C pointer to a struct): write chargeToll(tag, toll) that returns -1 for a missing tag or a toll <= 0, -2 if tag.balance < toll, and otherwise subtracts the toll from tag.balance (changing the caller's object) and returns 0.
Write an Account struct and functions Account *account_new(const char *name), int account_withdraw(Account *a, long paise) (returning an error code for insufficient funds), void account_print(const Account *a) and void account_free(Account *a). Create two accounts on the heap, transfer money between them with a function that takes two pointers, print both and free them.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Unions, enums and memory layoutStructs, unions, enums and files · same module
- Reading and writing text filesStructs, unions, enums and files · same module
- Structs and methodsGo Programming (backend and cloud) · Collections and structs
- Structs: your own data typesRust Programming · Structs, enums and pattern matching
- Structs, value types and reference typesC# and .NET · Classes and objects
- Classes and objects: data plus behaviourC++ Programming (modern C++ and DSA) · Classes, constructors and RAII
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
p->x is the same as…
Answer: (*p).x
Dereference, then select the member.
Why pass a large struct by pointer?
Answer: To avoid copying it, and to allow changes
Use const when only reading.
Can a struct contain a member of its own struct type (not a pointer)?
Answer: No: it would be infinitely large; it can contain a pointer to its type
Self-reference must be through a pointer.
What happens with p->x when p is NULL?
Answer: Undefined behaviour (usually a crash)
Always check pointers before ->.
Which operator accesses a member of a struct variable?Related
How does Go reuse code from another struct type?Related
Answer: Embedding (composition)
Embedding promotes the inner type's fields and methods to the outer type.
From Structs and methods
What is a struct?Related
Answer: A custom type that groups named fields
Structs group related values under one named type.
When is a struct a good choice?Related
Answer: For small, immutable, value-like data such as a point or money
Small, immutable values are the classic struct use.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 3 more topics in “Structs, unions, enums and files” before its exam: Unions, enums and memory layout, Reading and writing text files, Binary files and records.
- Module 7 exam: Structs, unions, enums and files · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, The preprocessor, multi-file programs and make. 60 topics left in the course before the final exam.