Pointers and Functions
Pointers are how C functions share data efficiently: output parameters, functions that modify arrays and structures in place, and functions that return pointers into existing data. This lesson collects the patterns — and the one pointer you must never return.
Output parameters
A function returns one value; pointer parameters let it produce more. The convention is to return a success flag and put results in the "out" parameters:
#include <stdio.h> #include <stdbool.h> bool parse_time(const char *text, int *hours, int *minutes) { int h, m; if (sscanf(text, "%d:%d", &h, &m) != 2) return false; if (h < 0 || h > 23 || m < 0 || m > 59) return false; *hours = h; *minutes = m; return true; } int main(void) { const char *inputs[] = { "09:45", "25:00", "noon" }; for (int i = 0; i < 3; i++) { int h, m; if (parse_time(inputs[i], &h, &m)) { printf("%-6s -> %d minutes after midnight\n", inputs[i], h * 60 + m); } else { printf("%-6s -> invalid\n", inputs[i]); } } return 0; }
09:45 -> 585 minutes after midnight 25:00 -> invalid noon -> invalid
Notice the function only writes to the outputs once it knows the input is valid — so a failed call never leaves the caller's variables half-changed.
In-out parameters
A pointer parameter can be read and updated:
#include <stdio.h> #include <stdbool.h> bool withdraw(long *balance_cents, long amount_cents) { if (amount_cents <= 0 || amount_cents > *balance_cents) return false; *balance_cents -= amount_cents; return true; } int main(void) { long balance = 10000; // 100.00 printf("%s\n", withdraw(&balance, 2550) ? "ok" : "declined"); printf("%s\n", withdraw(&balance, 9000) ? "ok" : "declined"); printf("balance: %ld.%02ld\n", balance / 100, balance % 100); return 0; }
ok declined balance: 74.50
Returning pointers
A function may return a pointer to data that outlives the call: an element of an array the caller passed in, a string literal, a static variable, or memory from malloc:
#include <stdio.h> const char *weekday_name(int day) { static const char *names[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; if (day < 1 || day > 7) return "???"; return names[day - 1]; // string literals live for the whole program } int *largest(int *values, size_t n) { int *best = &values[0]; for (size_t i = 1; i < n; i++) { if (values[i] > *best) best = &values[i]; } return best; // points into the caller's array } int main(void) { printf("%s %s\n", weekday_name(3), weekday_name(9)); int scores[] = { 70, 95, 88 }; *largest(scores, 3) = 100; // modify the winner in place printf("%d %d %d\n", scores[0], scores[1], scores[2]); return 0; }
Wed ??? 70 100 88
Never return a pointer to a local variable
A local variable disappears when its function returns (lesson 23). Returning its address hands back a "dangling" pointer:
#include <stdio.h> char *make_greeting(const char *name) { char buffer[64]; snprintf(buffer, sizeof buffer, "Hello, %s!", name); return buffer; } int main(void) { printf("%s\n", make_greeting("Ada")); return 0; }
main.c:6:12: warning: address of stack memory associated with local variable 'buffer' returned [-Wreturn-stack-address]
Three correct alternatives: let the caller provide the buffer; allocate with malloc and make the caller free it (lesson 36); or return a struct by value. The first is the most common in C libraries:
#include <stdio.h> char *make_greeting(char *buffer, size_t size, const char *name) { snprintf(buffer, size, "Hello, %s!", name); return buffer; } int main(void) { char text[64]; printf("%s\n", make_greeting(text, sizeof text, "Ada")); return 0; }
Hello, Ada!
Optional parameters with NULL
Passing NULL for an output the caller doesn't need is a common convention — the function checks before writing:
#include <stdio.h> int count_words(const char *s, int *longest) { int words = 0, best = 0, current = 0; for (;; s++) { if (*s == ' ' || *s == '\0') { if (current > 0) words++; if (current > best) best = current; current = 0; if (*s == '\0') break; } else { current++; } } if (longest != NULL) *longest = best; return words; } int main(void) { int longest; printf("%d words\n", count_words("a short sentence here", NULL)); printf("%d words, ", count_words("pointers are powerful", &longest)); printf("longest has %d letters\n", longest); return 0; }
4 words 3 words, longest has 8 letters
Try it yourself
Write a function that computes the mean and the standard deviation of an array, returning both through pointers.
mean 1.712 m, standard deviation 0.061 m