Reputation: 41483
I want to store a 4-byte int in a char array... such that the first 4 locations of the char array are the 4 bytes of the int.
Then, I want to pull the int back out of the array...
Also, bonus points if someone can give me code for doing this in a loop... IE writing like 8 ints into a 32 byte array.
int har = 0x01010101;
char a[4];
int har2;
// write har into char such that:
// a[0] == 0x01, a[1] == 0x01, a[2] == 0x01, a[3] == 0x01 etc.....
// then, pull the bytes out of the array such that:
// har2 == har
Thanks guys!
EDIT: Assume int
are 4 bytes...
EDIT2: Please don't care about endianness... I will be worrying about endianness. I just want different ways to acheive the above in C/C++. Thanks
EDIT3: If you can't tell, I'm trying to write a serialization class on the low level... so I'm looking for different strategies to serialize some common data types.
Upvotes: 26
Views: 74465
Reputation: 195
char a[10];
int i=9;
a=boost::lexical_cast<char>(i)
found this is the best way to convert char into int and vice-versa.
alternative to boost::lexical_cast is sprintf.
char temp[5];
temp[0]="h"
temp[1]="e"
temp[2]="l"
temp[3]="l"
temp[5]='\0'
sprintf(temp+4,%d",9)
cout<<temp;
output would be :hell9
Upvotes: 1
Reputation: 413
#include <stdint.h> int main(int argc, char* argv[]) { /* 8 ints in a loop */ int i; int* intPtr int intArr[8] = {1, 2, 3, 4, 5, 6, 7, 8}; char* charArr = malloc(32); for (i = 0; i < 8; i++) { intPtr = (int*) &(charArr[i * 4]); /* ^ ^ ^ ^ */ /* point at | | | */ /* cast as int* | | */ /* Address of | */ /* Location in char array */ *intPtr = intArr[i]; /* write int at location pointed to */ } /* Read ints out */ for (i = 0; i < 8; i++) { intPtr = (int*) &(charArr[i * 4]); intArr[i] = *intPtr; } char* myArr = malloc(13); int myInt; uint8_t* p8; /* unsigned 8-bit integer */ uint16_t* p16; /* unsigned 16-bit integer */ uint32_t* p32; /* unsigned 32-bit integer */ /* Using sizes other than 4-byte ints, */ /* set all bits in myArr to 1 */ p8 = (uint8_t*) &(myArr[0]); p16 = (uint16_t*) &(myArr[1]); p32 = (uint32_t*) &(myArr[5]); *p8 = 255; *p16 = 65535; *p32 = 4294967295; /* Get the values back out */ p16 = (uint16_t*) &(myArr[1]); uint16_t my16 = *p16; /* Put the 16 bit int into a regular int */ myInt = (int) my16; }
Upvotes: 2
Reputation: 1
union value { int i; char bytes[sizof(int)]; }; value v; v.i = 2; char* bytes = v.bytes;
Upvotes: 0
Reputation: 6208
Note: Accessing a union through an element that wasn't the last one assigned to is undefined behavior. (assuming a platform where characters are 8bits and ints are 4 bytes) A bit mask of 0xFF will mask off one character so
char arr[4];
int a = 5;
arr[3] = a & 0xff;
arr[2] = (a & 0xff00) >>8;
arr[1] = (a & 0xff0000) >>16;
arr[0] = (a & 0xff000000)>>24;
would make arr[0] hold the most significant byte and arr[3] hold the least.
edit:Just so you understand the trick & is bit wise 'and' where as && is logical 'and'. Thanks to the comments about the forgotten shift.
Upvotes: 9
Reputation: 21721
You can also use placement new for this:
void foo (int i) {
char * c = new (&i) char[sizeof(i)];
}
Upvotes: 4
Reputation:
Not the most optimal way, but is endian safe.
int har = 0x01010101;
char a[4];
a[0] = har & 0xff;
a[1] = (har>>8) & 0xff;
a[2] = (har>>16) & 0xff;
a[3] = (har>>24) & 0xff;
Upvotes: 25
Reputation: 503815
Don't use unions, Pavel clarifies:
It's U.B., because C++ prohibits accessing any union member other than the last one that was written to. In particular, the compiler is free to optimize away the assignment to
int
member out completely with the code above, since its value is not subsequently used (it only sees the subsequent read for thechar[4]
member, and has no obligation to provide any meaningful value there). In practice, g++ in particular is known for pulling such tricks, so this isn't just theory. On the other hand, usingstatic_cast<void*>
followed bystatic_cast<char*>
is guaranteed to work.
– Pavel Minaev
Upvotes: 8
Reputation: 3637
int main() {
typedef union foo {
int x;
char a[4];
} foo;
foo p;
p.x = 0x01010101;
printf("%x ", p.a[0]);
printf("%x ", p.a[1]);
printf("%x ", p.a[2]);
printf("%x ", p.a[3]);
return 0;
}
Bear in mind that the a[0] holds the LSB and a[3] holds the MSB, on a little endian machine.
Upvotes: 8
Reputation: 118128
#include <stdio.h>
int main(void) {
char a[sizeof(int)];
*((int *) a) = 0x01010101;
printf("%d\n", *((int *) a));
return 0;
}
Keep in mind:
A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined.
Upvotes: 9
Reputation: 101565
Unless you care about byte order and such, memcpy
will do the trick:
memcpy(a, &har, sizeof(har));
...
memcpy(&har2, a, sizeof(har2));
Of course, there's no guarantee that sizeof(int)==4
on any particular implementation (and there are real-world implementations for which this is in fact false).
Writing a loop should be trivial from here.
Upvotes: 42