Spartan 117
Spartan 117

Reputation: 619

Getting the starting address of the start of a struct

struct foo {
     long a;
     float d;
     void *some_ptr;
}

struct foo *start_address(void *some_other_ptr) {
    return ((struct test *)((char *) linkfield_ptr //Don't know what to do here);
}

int main() {
     struct foo fum;
     struct foo *foo_ptr;

     foo_ptr = start_address(&fum.some_ptr);
}

foo_ptr needs to be the starting address of the struct so basically the start_address method has to return that. I have been bashing my head against this problem for an hour or so as i am not allowed to use any macros or external libraries for find the answer. An answer to this as well as an explanation of how they got the answer from pointer gurus would be appreciated.

Upvotes: 1

Views: 623

Answers (1)

Jack
Jack

Reputation: 133587

If void* some_ptr is the first field of the struct then it's trivially the same address.

Otherwise a generic solution would be similar to the implementation of offsetof, something like:

unsigned int offset = &((struct foo*)0)->some_ptr;

complete example:

#include <stdio.h>
#include <stdint.h>

struct foo
{
    int padding1;
    unsigned char padding3;
    void* ptr;
    int padding2;
};

struct foo* start_address(void* ptr)
{
    uintptr_t offset = (uintptr_t)&((struct foo*)0)->ptr;
    return (struct foo*)(ptr - offset);
}

int main(void) {
    struct foo test;
    printf("%p == %p\n", &test, start_address(&test.ptr));
    return 0;
}

This is easy to think about, you cast address 0 to be considered the addres of a struct foo*, then if you try to obtain address of any field of that struct you get the offset (since you were starting from 0).

Upvotes: 1

Related Questions