I guess there are sort of two questions here:
- If a function is declared to return a value (or not), how wrong is it to not return a value (or to return a value)?
- If a function returns a value (or not), how wrong is it for the caller not to use the value (or to use the value)?
Let's examine these in turn.
First, if a function is declared to return a value (or not), how wrong is it to not return a value (or to return a value)?
There are four cases:
- function declared to return value, function does return value: this is obviously good and proper.
- function declared to return
void
, function does not return value: this is obviously good and proper.
- function declared to return
void
, function does return value: this is obviously an error, and the compiler will emit an error message and halt compilation.
- function declared to return value, function does not return value: this is probably an error, but for historical reasons, the compiler might not complain. Good compilers will at least issue a warning here. It sounds like your compiler didn't. You might want to think about getting a better compiler, or changing compilation options so it issues more warnings. (It's also possible for this situation not to be an error, as described in Eric Postpischil's answer, and this helps explains why the situation is not, in fact, illegal. There may also be subtle differences between the case where the function "falls off the end" and hits the terminating
}
without ever having a return
statement, versus the case where it has an explicit return;
statement without a value.)
That might answer your question, but if not, let's move on to my second question: if a function returns a value (or not), how wrong is it for the caller not to use the value (or to use the value)?
Again, there are four cases:
- function declared to return value, caller uses return value: this is obviously good and proper.
- function declared to return
void
, caller does not use return value: this is obviously good and proper.
- function declared to return
void
, caller does use return value: this is obviously an error, and the compiler will emit an error message and halt compilation.
- function declared to return value, caller does not use return value: this is the interesting case. It might be a problem, or it might not be a problem. Let's expand on this further:
For a function like sqrt
, whose sole function is to compute and return a value, it would obviously be very strange to not use the return value. For example, if you write
sqrt(100);
alone on a line, you're asking to compute the square root of 100, and then throwing away the return value. This is not an error, but a good compiler will probably warn about it, because it's probably not what you want.
There are other functions that return a value, that you might not care about. For example, it's not well known that the venerable printf
function returns a value: the number of characters printed. But printf
is not a function whose sole function is to compute and return a value; printf
also does something interesting off to the side: it prints stuff. So if you call
printf("Hello, world!\n");
but if you throw away the return value, that's fine, almost no one would object to that. (Theoretically there's a chance that printf
might fail, due to some kind of an i/o error, and return -1 to try to tell you this, but most programs don't care about this, and in the grand scheme of things that's not a problem.)
Finally, there are programs that return a value, that you might not think you care about, but that you probably should care about. Consider this fragment:
int i;
printf("enter an integer:\n");
scanf("%d", &i);
printf("you typed %d\n, i);
Here, the problem is that if the user types something like "no, I won't", scanf
will be unable to read an integer as requested by %d
, and it will return 0 to say that it performed no conversion, but the program won't notice, and since i
is an uninitialized value, it's hard to see what the program might print.
If we think about this carefully, we see that there might be sort of a "hidden" attribute of functions, namely: "How okay is it for the caller to ignore the return value?" printf
is a function that returns int
, but it's usually (in all but the most paranoid programs) okay to ignore the return value. But scanf
is a function that returns int
where, as we've just seen, it's not a good idea to ignore the return value (although lots of programmers do). And sqrt
is a function returning double
, where it's almost certainly an error not to use the return value. So if a compiler decides to help you out by warning you when you forget to use a function's return value, how does it avoid spamming you with warnings every time you call printf
? And the answer is that such a compiler has to invent a special way to implement that property -- a property not defined by the C language, which is why I called it "hidden" -- that specifies whether or not the warning is appropriate.
Also -- and this gets down to the meat of your question as asked -- there's a higher-order question that sort of combines the two top-level questions I've been exploring: If a function is declared as returning a value, but does not return a value, what happens if the caller does/doesn't try to use the returned value?
And the answer is that if a function is declared as returning a value, but it doesn't actually return a value, but the caller doesn't try to use the return value, that's fine -- although this might seem like kind of a dicey situation! And on the other hand, if the caller does try to use the value that wasn't returned, that's obviously a bad situation. As far as the C Standard is concerned, it falls into the dreaded category of undefined behavior, and there's a pretty good reason for this: deciding whether it's actually a problem is a hard, almost impossible problem. If a function is declared as returning a value, and if it sometimes doesn't return a value, and if the caller sometimes doesn't try to use the returned non-value, deciding whether it's actually a problem would theoretically requiring (a) examining the code for both the function and its caller and (b) deciding under which circumstances the function does or doesn't return a value. Both of these subproblems are basically impossible to solve. C supports separate compilation, so in the general case a compiler won;t be able to inspect both the function and its caller at once. And solving subproblem (b) is basically the halting problem. So it's up to you, the programmer, to keep things straight in this case: the compiler can't be required to issue an error if you try to use the value that wasn't returned by a function declared as if it returned one.
In the end, though, the Swap()
function you posted could probably an example of the "don't care" case. It's defined as returning int *
, but it doesn't actually return a value, but the caller doesn't try to use it, so it's okay. But this is potentially quite confusing and error-prone, so I would suggest that it would be much better to either (a) have it actually return a value or (b) redeclare it as returning void
.