Convert short to byte array

P

porcelli.giuseppe

Sorry for this stupid question by I am very new to C++

how to convert this routine to C++ ?

private byte[] getByteFromShort(short x) {
byte[] a = new byte[2];
a[0] = (byte) (x & 0xff);
a[1] = (byte) ((x >> 8) & 0xff);
return a;
}

Thank you.
 
V

Victor Bazarov

Sorry for this stupid question by I am very new to C++

how to convert this routine to C++ ?

private byte[] getByteFromShort(short x) {
byte[] a = new byte[2];
a[0] = (byte) (x & 0xff);
a[1] = (byte) ((x >> 8) & 0xff);
return a;
}

It's almost in C++ already. Literal translation might look like this:

typedef unsigned char byte;
....
byte* getByteFromShort(short x) {
byte* a = new byte[2];
a[0] = x & 0xff;
a[1] = (x >> 8) & 0xff;
return a;
}

Managing access level ('private', 'public' or 'protected') is left to
the reader.

Now, whether this fits your needs, I don't know, you didn't explain how
this function is going to be used.

V
 
N

Nobody

Sorry for this stupid question by I am very new to C++

how to convert this routine to C++ ?

private byte[] getByteFromShort(short x) {
byte[] a = new byte[2];
a[0] = (byte) (x & 0xff);
a[1] = (byte) ((x >> 8) & 0xff);
return a;
}

Bare (C-style) arrays can't be returned by value. You need to use
e.g. std::array (std::tr1::array prior to C++11), e.g.:

std::array<uint8_t, 2> getByteFromShort(uint16_t x) {
std::array<uint8_t, 2> a;
a[0] = (uint8_t) (x & 0xff);
a[1] = (uint8_t) ((x >> 8) & 0xff);
return a;
}

If you really want to use a bare array, have the caller pass it in:

void getByteFromShort(uint16_t x, uint8_t a[2]) {
a[0] = (uint8_t) (x & 0xff);
a[1] = (uint8_t) ((x >> 8) & 0xff);
}

Note 1: although C++ has a "short" type, it's not guaranteed to be
exactly 16 bits. It is guaranteed to be at least 16 bits.

Note 2: Signed integral types aren't guaranteed to use two's-complement
representation. The result of performing a right shift on a negative
integer is implementation-defined.

Fortunately, all C++ integral types have both signed and unsigned
versions, so you aren't coerced into using signed integers inappropriately
(unlike in Java).
 
V

Victor Bazarov

Sorry for this stupid question by I am very new to C++

how to convert this routine to C++ ?

private byte[] getByteFromShort(short x) {
byte[] a = new byte[2];
a[0] = (byte) (x & 0xff);
a[1] = (byte) ((x >> 8) & 0xff);
return a;
}

Bare (C-style) arrays can't be returned by value. You need to use
e.g. std::array (std::tr1::array prior to C++11), e.g.:

std::array<uint8_t, 2> getByteFromShort(uint16_t x) {
std::array<uint8_t, 2> a;
a[0] = (uint8_t) (x & 0xff);
a[1] = (uint8_t) ((x >> 8) & 0xff);
return a;
}

If you really want to use a bare array, have the caller pass it in:

void getByteFromShort(uint16_t x, uint8_t a[2]) {

To the OP: this is a bit dangerous. The second argument is an address
of a 'uint8_t' value, but there is no guarantee that it points to an
array of two such values (so the index 1 can be used), and there is no
way for the compiler to verify that. I would probably recommend passing
this array by reference:

void getByteFromShort(uint16_t x, uint8_t (&a)[2]) {
a[0] = (uint8_t) (x & 0xff);
a[1] = (uint8_t) ((x >> 8) & 0xff);
}

[..]

V
 
V

Victor Bazarov

Victor Bazarov said:
It's almost in C++ already. Literal translation might look like this:

typedef unsigned char byte;
...
byte* getByteFromShort(short x) {
byte* a = new byte[2];
a[0] = x & 0xff;
a[1] = (x >> 8) & 0xff;
return a;
}

Given that you are a frequent visitor of this newsgroup and you probably
know C++ better than the average programmer, I find it extremely puzzling
why you would recommend such a horrible, horrible solution to the question
that was posed.

(a) You didn't provide *any* solution.

(b) You haven't bothered to explain (to those who need an explanation,
like the OP, for instance) why you consider this solution horrible.

Given that such an attitude is frequent in your posts, I find it no
surprise whatsoever why you would continue posting in this manner.

V
 
V

Victor Bazarov

Am 01.03.13 17:55, schrieb Victor Bazarov:
It's almost in C++ already. Literal translation might look like this:

typedef unsigned char byte;
...
byte* getByteFromShort(short x) {
byte* a = new byte[2];
a[0] = x & 0xff;
a[1] = (x >> 8) & 0xff;
return a;
}
why you would recommend such a horrible, horrible solution
(b) You haven't bothered to explain (to those who need an explanation,
like the OP, for instance) why you consider this solution horrible.

Well, I think that is pretty clear: your solution returns a newly
allocated buffer by pointer. That calls for manual memory management. If
one considers that a pointer in today's computers takes up at least four
bytes, it is also less efficient than returning the two bytes by value
in a structure. Even doing an inline function like this might be more
efficient:

unsigned char getByteFromShort(short x, size_t i) {
if (i==0) return x & 0xff;
if (i==1) return (x>>8) & =xff;
throw std::eek:ut_of_range("Index in short must be 0 or 1");
}

There is a very big assumption concerning the way this function is
supposed to be used. Your crystal ball must be in much better order
than mine if you can divine what the OP wanted (as you clearly do here).

V
 
I

Ian Collins

Christian said:
Am 01.03.13 17:55, schrieb Victor Bazarov:
It's almost in C++ already. Literal translation might look like this:

typedef unsigned char byte;
...
byte* getByteFromShort(short x) {
byte* a = new byte[2];
a[0] = x & 0xff;
a[1] = (x >> 8) & 0xff;
return a;
}
why you would recommend such a horrible, horrible solution
(b) You haven't bothered to explain (to those who need an explanation,
like the OP, for instance) why you consider this solution horrible.

Well, I think that is pretty clear: your solution returns a newly
allocated buffer by pointer. That calls for manual memory management. If
one considers that a pointer in today's computers takes up at least four
bytes, it is also less efficient than returning the two bytes by value
in a structure.
Why?

Even doing an inline function like this might be more
efficient:

unsigned char getByteFromShort(short x, size_t i) {
if (i==0) return x & 0xff;
if (i==1) return (x>>8) & =xff;
throw std::eek:ut_of_range("Index in short must be 0 or 1");
}

So you propose a "safe" solution that doesn't do what the OP wanted (an
array of two bytes)?
 
S

Stefan Ram

Ian Collins said:
So you propose a "safe" solution that doesn't do what the OP wanted (an
array of two bytes)?

One might return an int value as a kind of array of two char values.
This should not require memory allocation, but only works where
sizeof( int )>=2.

The Java code seems to assume CHAR_BITS==8, which is true in
Java, but might not be true in C++. A group of 8 bits actually
is an »octett«, not a »byte«. Even, where sizeof( int )>=2
is not true, an int should be able to carry two octetts.
 
I

Ian Collins

Christian said:
Am 01.03.13 23:56, schrieb Ian Collins:
So you propose a "safe" solution that doesn't do what the OP wanted (an
array of two bytes)?


OK, OK, I changed the topic.

typedef std::array<unsigned char,2> twobyte;

twobyte getByteFromShort(short x) {
twobyte result;
result[0]=x & 0xff;
result[1]=(x>>8) & 0xff;
}

Happy? Or does "array" imply "C-style array"?

Why should it?
IMHO translating Java-new to C++-new should be avoided, because in C++
RAII is the idiomatic way for memory management, whereas the GC takes
care of the array in Java. I think this is worth pointing out to a newbie.

BTW, on my machine gcc -O3 translates the above function into "rep;
ret", i.e. do nothing.

Because you didn't return result....
 
A

Alain Ketterlin

how to convert this routine to C++ ?

private byte[] getByteFromShort(short x) {
byte[] a = new byte[2];
a[0] = (byte) (x & 0xff);
a[1] = (byte) ((x >> 8) & 0xff);
return a;
}

Other answers give you detailed (and important) information about a
(more or less) literal translation of this code. I'd like to add that I
would not even write a function for such a simple operation:

int8_t xbytes [] = { x, x>>8 };

Of course, whether this is useful depends on what you are going to do
with the array (which will live on the stack of the "calling" context).
Dynamic allocation is not cheap, C++ has no garbage collection by
default, so it's better to avoid putting pressure on the allocator for
such minuscule pieces of data. If you are going to pass this "array"
around, you should prefer data structures that carry their own size. But
are you really going to pass around the two bytes of a short? In actual
code, I would probably use either x and x>>8, or two distinct variables.

Note also that 1) I've used int8_t to respect Java's signedness of
bytes, you could switch to uint8_t to have unsigned bytes; 2) iirc,
these types are not guaranteed to exist; 3) I didn't bother to zero out
bits that get truncated later (this applies to your Java code as well,
where both "&0xff" are absolutely useless), but this is valid only if
int8_t exists (otherwise, more care is needed, depending on the later
usage of these "bytes").

-- Alain.
 
V

Victor Bazarov

Victor Bazarov said:
[..]
Given that such an attitude is frequent in your posts

Frequent? Care to give some examples?

No. I don't care to continue this particular train of discussion and am
going to give you the chance to wrap it up since it was you who started it.

Have a good one!

V
 
J

James Kanze

(e-mail address removed) writes:
how to convert this routine to C++ ?
private byte[] getByteFromShort(short x) {
byte[] a = new byte[2];
a[0] = (byte) (x & 0xff);
a[1] = (byte) ((x >> 8) & 0xff);
return a;
}
Other answers give you detailed (and important) information about a
(more or less) literal translation of this code. I'd like to add that I
would not even write a function for such a simple operation:
int8_t xbytes [] = { x, x>>8 };

The advantage of the function is that if you change the format,
you just have one function to change.
Of course, whether this is useful depends on what you are going to do
with the array (which will live on the stack of the "calling" context).
Dynamic allocation is not cheap, C++ has no garbage collection by
default, so it's better to avoid putting pressure on the allocator for
such minuscule pieces of data. If you are going to pass this "array"
around, you should prefer data structures that carry their own size. But
are you really going to pass around the two bytes of a short? In actual
code, I would probably use either x and x>>8, or two distinct variables.

How about a:

struct BytesForShort
{
unsigned char bytes[ sizeof(short) ];
};

In most cases, of course, this would be part of a larger set of
serialization routines, and the output would be via a non-const
reference argument.
Note also that 1) I've used int8_t to respect Java's signedness of
bytes, you could switch to uint8_t to have unsigned bytes;

I think that you'ld almost certainly want an unsigned type.
2) iirc,
these types are not guaranteed to exist;

They are not. But since the starting point was Java, we can
assume they do. Otherwise, I don't think you could implement
Java on the machine.
3) I didn't bother to zero out
bits that get truncated later (this applies to your Java code as well,
where both "&0xff" are absolutely useless), but this is valid only if
int8_t exists (otherwise, more care is needed, depending on the later
usage of these "bytes").

I've gotten used to using the `0xFF` to make my intentions
clear, even if it isn't (usually) necessary. The compiler will
turn it into a no-op if it isn't necessary.
 
J

James Kanze

I think you mean that the compiler will remove if it's unnecessary?
Because a 'nop' is an actual opcode that takes a clock cycle (or such)
to execute, and would be useless baggage.

I wasn't thinking in terms of machine instructions, so much as
the more general meaning: no-op means "no operation", in other
words, do nothing. In particular, when I write something like:
"i & 0xFF", where i is an `int` in memory, all of the
compilers I know will simply generate a byte access for the low
order byte, with no and instruction; similarly, for "(i >> 8)
& 0xFF" or "(i & 0xFF00) >> 8" (although I'm not sure about the
latter---I tend to write the former, and I've only really looked
at generated code for code I've written).
 
J

Jorgen Grahn

Sorry for this stupid question by I am very new to C++

how to convert this routine to C++ ?

private byte[] getByteFromShort(short x) {
byte[] a = new byte[2];
a[0] = (byte) (x & 0xff);
a[1] = (byte) ((x >> 8) & 0xff);
return a;
}

Thank you.

Since the responses soon made it clear that the interface design is
the problem, here's how I usually do it:

namespace bigendian {

uint8_t* put16(uint8_t* p, unsigned val);
void put16(uint8_t*& p, unsigned val);
}

- Assumes your "shorts" are really unsigned.

- Either updates the buffer pointer or returns a new one;
feel free to pick one. I find that it's best to let the
function reveal this information, even if we know that
exactly two bytes will be used.

- A template which uses output iterators is more useful.

- This is a simple case of serialisation -- representing
C++ objects as octet arrays. There are people who do
this a lot and do elaborate things; I am not one of them.
I just do things like building IPv4 headers.

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top