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
returnin a function that has a return type other thanvoidis 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
intis returned in the%eaxregister. In your case, the compiler also decided to use this register to calculate the new value ofc– 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 calculatingc, you’d have seen something else.