开发者

Copying between byte array and unsigned long

What's the best/recommended way to copy data between a byte array and an integer in C? Currently I'm using memcpy, which doesn't feel right to me. A sample of the sort of thing I'm doing is below.

struct alpha {
        unsigned char byte_array[20];
}

void function(struct alpha *st) {
        unsigned long num;

        /* Do some stuff */
开发者_JAVA技巧
        memcpy(st->byte_array, &num, sizeof(unsigned long));

        /* Do more stuff */

        memcpy(&num, st->byte_array, sizeof(unsigned long));
}

I assume I want to use casts somehow, but I'm not confident of how casting and pointer (de)referencing interacts, particularly when arrays get involved.


memcpy is the standard and portable tool for that effect. Modern optimized compilers will inline this call to something well adapted to your situation, e.g data types, allignement, size (if known at compile time), processor... So I think you should definitively stick to that and not mess around with some handmade optimizations.


It looks exactly the right way to me. Which is to say, when I had to do this, it was the way I did it.


Here's how to do it with casts:

    /* Do some stuff */

    *(unsigned long *)st = num;

    /* Do more stuff */

    num = *(unsigned long *)st;

You're casting your struct pointer to a pointer to an unsigned long, then dereferencing the pointer in the assignment statements.


It is not wrong, unless you know that "who" wrote the data into the array wrote them in an endianness different from the one used on your system. Say, e.g., if those data come from a "stream" sent by "someone" over the net. Then, if the protocol uses the so called "network byte order" (namely big endian), and your machine is not big endian, then you obtain wrong values.


Is there any particular reason you need to copy instead of just aliasing the two? e.g.:

union XXX { char byte_array[20]; unsigned long num; };

In theory, you don't get defined results when you write to one member of the union then read from the other member. In reality, there's essentially no possibility of getting anything different from what you're getting now -- except (of course) that you don't have to copy data to get from one view to the other -- you just use x.num to look at it as an unsigned long, and x.byte_array to look at it as an array of bytes.


memcpy is the safest way to do this sort of thing. If speed matters though, you can do some cast magic to let the compiler handle the copy natively for you:


*((unsigned long *)&st->byte_array[0]) = num;

num = *((unsigned long *)&st->byte_array[0]);

Both these will use built in register type copies instead of a function call of 4 bytes. If you want to read further into the byte_array, you must be careful of byte alignment issues with this though.


I prefer some default functions for this requirement,

for string to integer

int atoi ( const char * str );

and for integer to string

char *  itoa ( int value, char * str, int base );


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

int main()
{
 unsigned long int number;
 unsigned char string[256];

 printf ("Enter a number: ");
 fgets ( string, 256, stdin );
 number = atoi (string);
 printf("number = %d\n",number);

 //converting int to string
 itoa (number,string,10);    //10 is base here for decimal, 16 is used for Hex and 2 for Binary
 printf ("string = %s\n",string);

 return 0;
}

as per me atoi() function is fine. But in case you don't want to use itoa() or it is not available to you then you can just use sprintf()

sprintf (string,"%ld",number);

I hope it helps

Thanks Alok.kr.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜