I would expect main to look like
int main(void) { int a, b, c; scanf("%d %d %d", &a, &b, &c); printf("%d\n", find_second(a, b, c)); }
Obviously your original function wouldn't work with this, but it's much more straight forward. Read in the input, process it, output the results.
void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } void sort(int *a, int *b, int *c) { if (*a > *b) { swap(a, b); } /* a <= b now */ if (*b > *c) { swap(b, c); if (*a > *b) { swap(a, b); } } /* a <= b <= c */ } int find_second(int a, int b, int c) { sort(&a, &b, &c); return b; }
Hopefully swap is clear. It just exchanges the two values.
The sort function now sorts the three values such that afterwards, \$a \le b\$ and \$b \le c\$. It may seem like you are checking a and b twice, but realize that they could change in between. So the second time you could be comparing the original a or b to the original c.
Once sorted, we can just return b, which is the middle value.
In my opinion, this is the most readable version. You might be able to get better performance by multiplying or taking the exclusive or, but this is the most understandable.
I'm also not convinced that it is slower. Note that a ^ b ^ c ^ smallest ^ largest does four register assignments (of intermediate results) and min and max each do two comparisons and two register assignments. At worst, this version does three comparisons and nine register assignments. At best, this version does no assignments and two comparisons. The min/max solutions always do at least four comparisons and eight assignments. In many systems, each if comparison involves a register assignment and then a branch command. So four branches against three.
You'd have to test to be sure how each version performed. Note that you'd likely have to do a large number of operations to get a good test, as both versions are going to be very fast on an individual basis. Actual speed may depend on how the compiler is able to optimize them.
An alternative is to use an array instead.
int compare_int(const void *a, const void *b) { return ( *(int *)b - *(int *)a ); } int find_second(int *data, int size) { qsort(data, size, sizeof *data, compare_int); return data[1]; } int main(void) { int data[3]; scanf("%d %d %d", &data[0], &data[1], &data[2]); printf("%d\n", find_second(data, 3)); }
This allows us to use the standard qsort and avoid defining our own sort.
It also scales well. It's easy to return a different ordinal value or to handle more values.
1,1,1or1,2,2? You return-1that's obviously, but what I'd expect is1for the first case and1for the second one. \$\endgroup\$<operations) performed by your current code, on average and in the worst case. Can you do it in fewer? \$\endgroup\$