First, you were smart to use calloc to make sure your result buffer had a zero at the end.
But it also put the zero at the beginning!
Your loop termination condition was j > 0 meaning you never filled slot 0 in the result.
So when you try to print p, the first character in the buffer it points to contains a \0 -- marking the end of a string, so your result is always the empty string.
I've done a little "fix" at http://codepad.org/QppfYQkm (I did not change the formatting, and I hardcoded the argument so it would be self-contained.)
Aside: I removed your check for if (len == 1) return str. Do not do this! If you have a one-character string, you will be returning the same buffer as that which held your argument, meaning changes to that result would destroy your input. Keep these buffers separate.
You were really close. :)
ADDENDUM
Here is some code using a commandline argument:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
char *rev(char *str) {
char *q = str;
int len = strlen(str);
char *p = (char*)calloc(len + 1, sizeof(char));
int j;
if (NULL == str) return NULL;
for (j = len-1 ; j >= 0 ; j--) {
p[j] = *q;
q++;
}
return p;
}
int main(int argc, char **argv) {
if (argc > 1) {
char *t = argv[1];
char *p ;
printf("%s\n",t);
p = rev(t);
printf("%s\n",p);
return 0;
}
}
When I run it:
$ gcc rev.c && ./a.out "hello there, reverse me"
hello there, reverse me
em esrever ,ereht olleh
$ gcc rev.c && ./a.out ""
$ gcc rev.c && ./a.out
$
The program works fine with text and with the empty string. It silently does nothing when given no argument.