简体   繁体   中英

Type casting struct to short/int for saving value on adress

I would like to know, if its possible to cast struct to short but only 2 bites of its adress and save value in there. I personally dont even know if its possible just wanna get any ideas how to do that.

In my project i link void adress of char to struct and then doing something similar like malloc but without using malloc.. making somthing like function malloc.

My struct and its pointer:

    typedef struct mem_list {
    int size;
    struct mem_list *next;
    struct mem_list *prev;
}mem_list;

mem_list *start;

my function memory init:

void memory_init(void *ptr, unsigned int size){

    mem_list *temp;
    temp = (mem_list*)ptr;
    if(size <= sizeof(mem_list)){
        temp->size = 0;
        printf("Failed\n");
        return;
    }

    else
    {
        temp->size = size - sizeof(mem_list);
        temp->next = NULL;
        *((unsigned short*)(&temp + size - sizeof(unsigned short))) = 0;
        start = temp;

        printf("Inicialized was %d bits\n",size-sizeof(mem_list));
        return;

    }
}

My main:

int main() {

    char region[100];

    memory_init(region, 60);

    //char* pointer = memory_alloc(20);

    //printf("adresa %d\n", pointer);

    return 0;
}

My problem is in function memory init in this part of code:

*((unsigned short*)(&temp + size - sizeof(unsigned short))) = 0;

What i want to do is to move to end of my inicialized memory and save there short typed zero for showing me later where is end of my memory. And also would like to ask how can i acces that value later? I know there maybe are mistakes in my code. Woul be happy if you point me where and give me some ideas how to do that. thank you :)

(&temp + size - sizeof(unsigned short))) : &temp is the address of the pointer to your mem_list , so &temp + xxx is the address of somewhere in the stack :-(

The address of the last byte of your mem_list object is (char*)temp + size .


To be cleaner you could define your

typedef struct mem_list {
    int size;
    struct mem_list *next;
    struct mem_list *prev;
    unsigned short  body[]
} mem_list_t ;

Then:

    blen  = (size + sizeof(unsigned short) - 1) / sizeof(unsigned short) ;
    temp->body[blen] = 0 ;

writes 0 to the last unsigned short of the body of the mem_list_t .

Note that this assumes that ptr points to an object which has been allocated with asize bytes:

    asize = offsetof(mem_list_t, body[blen+1]) ;

with blen calculated as above. (And ptr needs to be aligned as required for mem_list_t , of course.)

It is not clear whether you can reuse a char buffer to create objects of other types in it(*), but you should at least care about alignment. Some processors require non char types to be correctly aligned, for example that:

  • the address of an int16_t shall be even
  • the address of an int32_t or larger shall be a multiple of 4

And even if some other processors do not enforce this rule, accessing mis-aligned data often adds a significant overhead. That is the reason for padding in structs.

So without more precautions, this line:

*((unsigned short*)(&temp + size - sizeof(unsigned short))) = 0;

could break because if size is odd, you are trying to write an unsigned short at an odd address.


(*) For more details, you can read that other post from mine, specialy the comments on my own answer

if its possible to cast struct to short but only 2 bites of its adress and save value in there

No, it isn't possible. *((unsigned short*)(&temp...) invokes undefined behavior. It is a so-called "strict aliasing violation" and can also lead to misalignment issues depending on system. What is the strict aliasing rule?

The rule of thumb is: never wildly cast between completely different pointer types. You need a lot of detailed knowledge about C in order to so in a safe manner.

You can do "type punning" either by using a union between the struct and a unsigned short though. Please note that endianess is an issue to consider when doing so.

Other than that, you can safely memcpy the contents of a struct into an allocated unsigned short or vice versa. memcpy is excempt from pointer aliasing rules and will handle alignment safely.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM