views:

230

answers:

5

I have a short integer variable called s_int that holds value = 2

unsighed short s_int = 2;

I want to copy this number to a char array to the first and second position of a char array.

Let's say we have char buffer[10];. We want the two bytes of s_int to be copied at buffer[0] and buffer[1].

How can I do it?

+6  A: 

The usual way to do this would be with the bitwise operators to slice and dice it, a byte at a time:

b[0] = si & 0xff;
b[1] = (si >> 8) & 0xff;

though this should really be done into an unsigned char, not a plain char as they are signed on most systems.

Storing larger integers can be done in a similar way, or with a loop.

crazyscot
A: 

If you don't want to make all that bitwise stuff you could do the following

char* where = (char*)malloc(10);
short int a = 25232;
where[0] = *((char*)(&a) + 0);
where[1] = *((char*)(&a) + 1);
Kotti
+4  A: 

*((short*)buffer) = s_int;

But viator emptor that the resulting byte order will vary with endianness.

Autopulated
Bingo. Easy and obvious.
Kotti
AKA quick and dirty ;)
Autopulated
gcc might tell you, `use of cast expressions as lvalues is deprecated`.
John Ledbetter
seriously?! They can't ever actually break it though... sooo much c relies on them, esp. low level stuff.
Autopulated
man, no way - think about the alignment. If buffer points to an odd index in the memory - let's *assume* address 0xFFF01 you are in big trouble.
Iulian Şerbănoiu
@Iulian: I haven't heard of that restriction on x86, but of course it's fundamental to some other architectures.
crazyscot
@Iulian: this is not an issue on X86 (perhaps only on speed though...). However, this is important on other platforms such as IA64, MIPS, probably ARM and so on
botismarius
@crazyscot and @botismarius I agree with your remarks but we're referring to C; we should try to be portable as much as possible.
Iulian Şerbănoiu
Indeed, the deprecation warning I mentioned I saw on a msp430 platform, where memory alignment is an issue. I wasn't able to generate this warning on my amd64 box.
John Ledbetter
Autopulated
John Ledbetter: That code doesn't use a cast expression as an lvalue; it uses the result of the unary `*` operator as an lvalue, which is fine (because it *is* an lvalue). It does, however, still have the alignment problem. ("Using a cast as an lvalue" is an expression like `(int)x = 10;`)
caf
+3  A: 

By using pointers and casts.

unsigned short s_int = 2;
unsigned char buffer[sizeof(unsigned short)];

// 1.
unsigned char * p_int = (unsigned char *)&s_int;
buffer[0] = p_int[0];
buffer[1] = p_int[1];

// 2.
memcpy(buffer, (unsigned char *)&s_int, sizeof(unsigned short));

// 3.
std::copy((unsigned char *)&s_int,
          ((unsigned char *)&s_int) + sizeof(unsigned short),
          buffer);

// 4.
unsigned short * p_buffer = (unsigned short *)(buffer); // May have alignment issues
*p_buffer = s_int;

// 5.
union Not_To_Use
{
  unsigned short s_int;
  unsigned char  buffer[2];
};

union Not_To_Use converter;
converter.s_int = s_int;
buffer[0] = converter.buffer[0];
buffer[1] = converter.buffer[1];
Thomas Matthews
+1  A: 
ShinTakezou
The `memcpy()` is a good approach, but note that "preserving the endianness" is not always correct. crazyscot's answer puts the answer into the buffer with *known* endianness, which is often what is really needed (for example, if the buffer is to be saved to a file or sent across a network). Your answer puts the answer into the buffer with *host* endianness, which is also sometimes what is needed (but less often).
caf
yes of course: with "endiannes is preserved" I meant to say that the data are stored into buffer the same way a short is kept in memory, allowing direct accessing to the short value from buffer to, provided that the user does not need to change the endianness into something specific.
ShinTakezou
Though note that direct access to the short from the buffer is only possible if the buffer is correctly aligned for such access; in general if you are going to directly access it as a short you should have declared it as a `struct` containing a `short` member rather than as an array of `char`.
caf
on processor that need alignment, and on processor that needs alignment to 2-byte, buffer is aligned too so it is ok to access it; x86 as far as I know does not require it (likely, accesses to not aligned memory is only slower).
ShinTakezou