A hex dump for Android, should be suitable for other platforms as well.
LOGD(), same as DLOG(), plays the role of printf() because printf() does not work in Android. For platforms other than Android, you may #define DLOG printf.
dlog.h:
// Android logging
#include <android/log.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "~~~~~~", __VA_ARGS__)
#define DLOG(...) __android_log_print(ANDROID_LOG_DEBUG  , "~~~~~~", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "~~~~~~", __VA_ARGS__)
#define ELOG(...) __android_log_print(ANDROID_LOG_ERROR  , "~~~~~~", __VA_ARGS__)
#ifdef __cplusplus
extern "C" {
#endif
void log_dump(const void*addr,int len,int linelen);
void log_dumpf(const char*fmt,const void*addr,int len,int linelen);
#ifdef __cplusplus
}
#endif
dump.cpp:
#include <dlog.h>
//#include <alloca.h>
inline char hdigit(int n){return "0123456789abcdef"[n&0xf];};
#define LEN_LIMIT 8
#define SUBSTITUTE_CHAR '`'
static const char* dumpline(char*dest, int linelen, const char*src, const char*srcend)
{
    if(src>=srcend) {
        return 0;
    }
    int i;
    unsigned long s = (unsigned long)src;
    for(i=0; i<8; i++) {
        dest[i] = hdigit(s>>(28-i*4));
    }
    dest[8] = ' ';
    dest += 9;
    for(i=0; i<linelen/4 ; i++) {
        if(src+i<srcend) {
            dest[i*3] = hdigit(src[i]>>4);
            dest[i*3+1] = hdigit(src[i]);
            dest[i*3+2] = ' ';
            dest[linelen/4*3+i] = src[i] >= ' ' && src[i] < 0x7f ? src[i] : SUBSTITUTE_CHAR;
        }else{
            dest[i*3] = dest[i*3+1] = dest[i*3+2] = dest[linelen/4*3+i] = ' ';
        }
    }
    return src+i;
}
void log_dumpf(const char*fmt,const void*addr,int len,int linelen)
{
#if LEN_LIMIT
    if(len>linelen*LEN_LIMIT) {
        len=linelen*LEN_LIMIT;
    }
#endif
    linelen *= 4;
    static char _buf[4096];
    char*buf = _buf;//(char*)alloca(linelen+1); // alloca() causes the initialization to fail!!!!
    buf[linelen]=0;
    const char*start = (char*)addr;
    const char*cur = start;
    const char*end = start+len;
    while(!!(cur = dumpline(buf,linelen,cur,start+len))){DLOG(fmt,buf);}
}
void log_dump(const void*addr,int len,int linelen)
{
    log_dumpf("%s\n",addr,len,linelen);
}
Usage example:
log_dumpf("args: %s\n", &p, 0x20, 0x10);
Output:
args: 61efadc4 00 3c 17 01 6d bc 59 61 02 00 00 00 80 ae ef 61 `<``m`Ya```````a
args: 61efadd4 00 3c 17 01 00 00 00 00 31 a5 59 61 80 ae ef 61 `<``````1`Ya```a
UPDATE:
see dump.cpp and re_dump.h in reDroid (github), it includes a recursive dump that checks if a pointer is valid.