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.
精彩评论