Is there any way to do this with a cast?
Yes it is possible, with the following assumptions:
- You need to take care of the struct alignment (compiler specific):
 - #pragma pack(push, 1) ... #pragma pack(pop),
 - __attribute__((packed)), etc.
 
- You need to take care of the endianess between your architecture and the bytes in a buffer (make a conversion if needed) 
What you can do is to use void* c instead of uint8_t* c in the struct and then cast void* to a explicit pointer type.
Example 1:
#include <stdint.h>
#include <stdio.h>
#pragma pack(push, 1)
typedef struct {
    uint8_t a;
    uint16_t b;
    void* c;
} req;
#pragma pack(pop)
void f(uint8_t* Buf)
{
    req* r = (req*)Buf;
    printf("a: %02x\n", r->a);
    printf("b: %04x\n", r->b);
    printf("c: %02x\n", ((uint8_t*)&r->c)[0]);
}
int main()
{
    uint8_t buf[] = { 0x01, 0x02, 0x03, 0x04 };
    f(buf);
    return 0;
}
Output:
a: 01
b: 0302
c: 04
Example 2:
#include <stdint.h>
#include <stdio.h>
#pragma pack(push, 1)
typedef struct {
    uint8_t a;
    uint16_t b;
    void* c;
} req;
typedef struct {
    uint8_t cmd;
    uint16_t value;
} SubPacket;
#pragma pack(pop)
void f(uint8_t* Buf)
{
    req* r = (req*)Buf;
    printf("a: %02x\n", r->a);
    printf("b: %04x\n", r->b);
    SubPacket* sub_packet = (SubPacket*)&r->c;
    printf("cmd: %02x\n", sub_packet->cmd);
    printf("value: %04x\n", sub_packet->value);
}
int main()
{
    uint8_t buf[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
    f(buf);
    return 0;
}
Output:
a: 01
b: 0302
cmd: 04
value: 0605