For a class, I'm writing a simple crypt function. Everything works as expected:
int crypt(char *key, int (*callback)(int, char*, int, int))
{
int c, i = 0, n = strlen(key);
while((c = fgetc(stdin)) != EOF)
{
// only change the char if it's printable
if(c >= 32 && c <= 126)
c = callback(c, key, n, i);
fputc(c, stdout);
i++;
}
}
int encryptCallback(int c, char *key, int n, int i)
{
return (c - 32 + key[i % n]) % 95 + 32;
}
int decryptCallback(int c, char *key, int n, int i)
{
return (c - 32 - key[i % n] + 3 * 95) % 95 + 32;
}
Using the professor's test case, everything works. But when I initially wrote the callbacks, I ommited the return. They were coded up like:
int encryptCallback(int c, char *key, int n, int i)
{
c = (c - 32 + key[i % n]) % 95 + 32; // no return
}
int decryptCallback(int c, char *key, int n, int i)
{
c = (c - 32 - key[i % n] + 3 * 95) % 95 + 32; // no return
}
When I ran the code with the non-returning callbacks, the output was still correct when I applied the test case (and yes, I recompiled, I wasn't running the old code). I only noticed the 'error' when I compiled with -Wall.
So I'm confused. Why is c (in crypt()) getting the correct value after it is assigned to the return value of callback (when callback doesn't return anything)? c isn't a pointer, it's just a regular int.
P.S. The assignment has nothing to do with function pointers.
Failing to use return in a function that has a return type other than void is undefined behaviour, if the caller tries to use the return value of the function.
In this case, the undefined behaviour you were getting apparently was "it returned the value I wanted it to, anyway". You just got (un)lucky. (It has nothing to do with function pointers, though).
If you are compiling on x86, then the underlying reason it worked out is that most x86 calling conventions specify that a return value of type int is returned in the %eax register. In your case, the compiler also decided to use this register to calculate the new value of c - so the value just happened to be left there to reappear as the "return value". If you'd done some more calculations in the function after calculating c, you'd have seen something else.
This might probably have to do with the way, function values are returned on your platform. For example, on many x86 based platforms, the register EAX is used to return integer values. If the correct value happens to be in that register at the end of the function (due to the computation being made), then the caller will not perceive a difference: it's just as if the value had been put there intentionally with a return statement.
It's just (bad!) luck, that your code actually worked the first time around.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With