简体   繁体   中英

Assigning value to the address of member of a struct pointer

I have this code

  struct abc *obj=(struct abc *)malloc(sizeof(struct abc));
  uint8_t **j=(uint8_t *)(&obj+ sizeof(uint8_t));
  *j=5;
  printf("%d\n",obj->j);

What I am trying to do is to just move into the area pointed to by struct abc *obj and change the value of obj->j . I have created pointer to pointer that contains the address of &obj+sizeof(uint8_t) in this sizeof(uint8_t) will get us passed the area possessed by obj->i which is also uint8_t. but the code is not really working when I print obj->j which is still 0 How can I move into the memory area and change the value of j so obj->j will print 5

My system processor is x86-64

First, please add the definition of struct abc . I presume it looks like:

struct abc {
    uint8_t byte_we_want_to_skip;
    uint8_t j;
};

In this line:

uint8_t **j=(uint8_t *)(&obj+ sizeof(uint8_t));

This says take the address of obj as a struct abc pointer, then add sizeof(uint8_t) ie 1 to it, but since the type of the expression is struct abc * , it is one sizeof(struct abc) bytes that you move, which is probably not what you want. Also, that should be uint8_t *j . So, what you should be using:

uint8_t *j = (uint8_t *)((char *)&obj+ sizeof(uint8_t));

Note also that all this pointer fiddling is undefined behaviour, so it is not guaranteed to work everywhere. offsetof() is a better alternative, used like so:

uint8_t *j = (char *) &obj + offsetof(obj, j);

I think you just want to change the value of j by accessing the memory location. You can do so by directly accessing the location like this.

uint_t *j = &(obj->j);
*j = 5;

But if you want to change the value using skipping bytes then Ken YN's answer.

You need to access the address of obj without & because *obj is already a pointer:

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

struct abc {
    uint8_t byte_we_want_to_skip;
    uint8_t j;
};

int main(void) {
    struct abc *obj= malloc(sizeof(struct abc));
    uint8_t *j =  (uint8_t*)((char *)obj+ sizeof(uint8_t)); // remove the &
    *j = 5;
    printf("address of obj => %p - value in obj->j: %d\n",obj, obj->j);
    printf("address of   j => %p - value at j address: %d \n", j, *j);
    return 0;
}

output:

address of obj => 0x55bbc5f84260 - value in obj->j: 5
address of   j => 0x55bbc5f84261 - value at j address: 5 

Or you can have your struct on the stack and then you can use & to access its address:

int main(void) {
    struct abc obj;
    uint8_t *j =  (uint8_t*)((char *)&obj+ sizeof(uint8_t));
    *j = 5;

    printf("address of obj => %p - value in obj.j: %d\n", &obj, obj.j);
    printf("address of   j => %p - value at j address: %d \n", j, *j);

    uint16_t *a =  (uint16_t*)((char *)j - 1);
    printf("address of   a => %p - value at a address: %x \n", a, *a); // will print j * 100 in hexa
    *a = 42 | 3 << 8;
    printf("\naddress of obj => %p - value in obj.i: %d\n", &obj, obj.i);
    printf("address of obj => %p - value in obj.j: %d\n", &(obj.j), obj.j);
    printf("address of   j => %p - value of j: %d \n", j, *j);
    return 0;
}

I added an uint16_t to illustrate a bit more, output:

address of obj => 0x7ffecc5fa536 - value in obj.j: 5
address of   j => 0x7ffecc5fa537 - value at j address: 5 
address of   a => 0x7ffecc5fa536 - value at a address: 500 

address of obj => 0x7ffecc5fa536 - value in obj.i: 42
address of obj => 0x7ffecc5fa537 - value in obj.j: 3
address of   j => 0x7ffecc5fa537 - value of j: 3 

NB: We get 0x0500 because of little endianness : inside the cpu bytes are 0x00 followed by 0x05, but the variable a will read bytes values from right to left

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