Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Wednesday, February 10, 2016

void * assignment problem

void * assignment problem


I want to take some fields from packet struct using pointer arithmetic.But what is wrong with the code below ?
In first condition i think if i go 4 byte(2 short field) from beginning of packet i get tLow .But it does not give expected value.Additionally second case i want to get data field by going 12 byte from beginning of packet .What is wrong with my idea ?

struct packet{          short len;        short field;        int tLow;        int tHigh;        void *data;  }    int main()  {      struct packet pack;      struct packet *pck;        pack.len=3;      pack.field=34;      pack.tLow=712;      pack.tHigh = 12903;      pack.data = "message";        pck = &pack;      int *timeLow = (int * )pck + 4; // i want to get tLow       printf("Time Low :%d\n",*time);        char *msg = (char *)pck + 12 ;// want data       printf("Message :%s\n",msg);        return 0;  }  

Answer by Anders K. for void * assignment problem


when you write

int *timeLow = (int * )pck + 4  

you are treating 'pck' as a int pointer which depending on your system may be 4 or 8 bytes. That will not correctly offset into the struct because you are then telling it to have an offset of 4 int

instead you would need to do like this

int *timeLow = (int*)((short * )pck + 2);   

Answer by Justin Hamilton for void * assignment problem


Shorts are not necessarily 2 bytes long. All that is specified is that they are less-than or equal-to the size of ints. You should probably be using sizeof()

Answer by vulkanino for void * assignment problem


This is wrong: pack.data = "message"; You are using unallocated memory.

Also this: int *timeLow = (int * )pck + 4; is not guaranteed to work (struct alignment varies between compilers and systems).

Answer by Prof. Falken for void * assignment problem


You are looking for offsetof.

Your code could look like this:

int *timeLow = (int*) ((char*)pck + offsetof(struct packet, tLow);  

and as pmg pointed out,

int *timeLow = &(pck->tLow);  

is the canonical way of getting a pointer to a member of a struct.

This answer also brought pointer arithmetics on the table - which I learned today thanks to pmg.

Answer by Maister for void * assignment problem


Basically you are relying on undefined behavior. Struct alignment, etc. But anyways...

(int*)pck + 4. Will advance the pointer 4 * sizeof(int). This is wrong, we want to advance it by 1 if we assume that the struct is packed and sizeof(short) == 2, thus...

int *timeLow = (int * )pck + 1; // i want to get tLow   printf("Time Low :%d\n",*timeLow);  

prints the correct result.

As for the message, you need to do some dirty stuff. Since I'm on x86_64 the compiler chose to pad the void* on 8 byte boundaries, so the offset was 16 rather than the expected 12.

We're basically fetching a pointer to a void*. So the code will look like this:

char **msg = (char**)((char *)pck + 16) ;// want data   printf("Message :%s\n",*msg);  

NEVER write code like this, this just illustrates a point.

Answer by pmg for void * assignment problem


You definitely would be better using standard method

int *timeLow = &(pck->tLow);  

Compilers are allowed to insert padding bytes between any member of a struct. The rules for these padding bytes are, at best, implementation defined ... so you must consult your implementation manual to be certain how (or if) and how many bytes are inserted in your specific case. Also note the number of padding bytes might change from compilation to compilation with different options or from compiler to compiler (computer to computer, ...)

You can try to use the C macro offsetof, but it's not pretty:

size_t offset = offsetof(struct packet, tLow);  /* make sure offset is a multiple of sizeof (int*) */  int *timeLow = (int*)pck + offset / sizeof (int*);  

or, a little less ugly using a cast to (char*) and copying the code from other answers :-)

size_t offset = offsetof(struct packet, tLow);  int *timeLow = (int*)((char*)pck + offset);  

Oh! and there's a semi-colon missing in your source


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.