Every C programmer writes a swap function eventually — and half of them write the broken version first. This question from our C Programming Quiz App shows the working version and asks whether you can trust it. The answer hinges on the same rule as the last question: C copies arguments — so how does this function change the caller’s variables at all?
The Quiz Question
int a = 1, b = 2;
void swap(int *x, int *y) {
int t = *x; *x = *y; *y = t;
}
swap(&a, &b);
printf("%d %d", a, b);
What is printed by this code?
- 1 2
- 2 1
- Compile error
- Undefined behavior
The Correct Answer: 2 1
swap receives the addresses of a and b. Inside the function, *x and *y are not copies — they are the caller’s variables themselves, reached through the pointers. The three-step dance (save *x in t, overwrite *x with *y, write t into *y) exchanges the two values in place. Verified on gcc 13.3 and Apple clang 21, clean under -ansi -Wall -Wextra:
$ gcc -ansi -Wall -Wextra swap.c && ./a.out 2 1
Why Each Wrong Answer Is Wrong
Why not “1 2”?
“Nothing changed” is exactly what the by-value version does — the famous broken swap:
void swap(int x, int y) { /* copies! */
int t = x; x = y; y = t;
}
swap(a, b);
$ ./a.out 1 2
It swaps its two local copies with great care, then throws them away. The quiz version takes pointers, so picking “1 2” means overlooking the *s and &s that make all the difference. (This broken-swap variant is its own quiz question.)
Why not a compile error?
The types line up perfectly: &a and &b are int *, matching the parameters; every dereference is of a valid int *. Both compilers are silent with all warnings on.
Why not undefined behavior?
Both pointers refer to live, valid objects for the whole call, every access is properly typed, and the reads and writes are cleanly sequenced by the three separate statements. Passing &a to a function is the intended way to grant it write access — nothing dangling, nothing out of bounds, nothing unsequenced.
The Pointer-Parameter Pattern
This is the C idiom for “out parameters” — any function that needs to modify caller state takes addresses:
scanf("%d", &x); /* writes the parsed value into x */
pthread_create(&tid, ...); /* writes the new thread's id */
swap(&a, &b); /* writes both */
Three details worth internalizing. First, the pointers themselves are still passed by value — swap gets copies of the addresses, but copies of an address lead to the same objects. Second, the caller’s & is a visible signal at the call site: swap(&a, &b) announces “these may change”, which C++ references famously hide. Third, the temporary t is required — the XOR-swap “trick” without a temporary is an interview curiosity that breaks when both pointers alias the same object (swap(&a, &a) zeroes it) and optimizes worse than the honest version.
Frequently Asked Questions
How does a swap function work in C?
It takes pointers to the two variables and exchanges the pointed-to values through a temporary: t = *x; *x = *y; *y = t;. Called as swap(&a, &b), it leaves a and b exchanged in the caller.
Why does swap need pointers in C?
Because C passes arguments by value — a function receiving plain ints can only swap its own copies. Passing addresses gives the function access to the caller’s actual objects.
Is swapping without a temporary variable better?
No. The XOR/arithmetic tricks fail when both pointers point at the same object and are generally slower after optimization. Use the plain three-line temporary version.
Related Reading
- Pass by Value in C – Why inc(n) Doesn’t Change n
- C Program to Swap Two Variables
- Copying a Value Through a Pointer in C
- Pointers in C – Complete Guide
Recommended Books
- The C Programming Language – Kernighan & Ritchie (India) | Amazon.com
- C Programming: A Modern Approach – K.N. King (India) | Amazon.com
This question is #95 in the C Programming Quiz App — 155 questions with explanations covering functions, pointers, memory, and more.
Download on Google Play →