473,405 Members | 2,404 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

Endianness Converter

MrPickle
100 100+
I am trying to make a function to read in a value, then convert it to little endian.

I wrote this:
Expand|Select|Wrap|Line Numbers
  1. template<typename T>
  2. void Read(T& value, std::ifstream& in) {
  3.     std::vector<unsigned char> bytes(sizeof(T));
  4.     in.read(reinterpret_cast<char*>(&bytes[0]), sizeof(T));
  5.     value = 0;
  6.  
  7.     for(int i = 0; i < sizeof(T); i++) {
  8.         value |= (bytes[i] << i * 8);
  9.     }
  10. }
But this is only working for int and the compiler won't accept trying to give it a float or double.

Should I scrap the template and just overload it?
Nov 23 '08 #1
24 3410
weaknessforcats
9,208 Expert Mod 8TB
You can't use the |= operator with double. It only works for integer types.

You may have to use an explicit specialization for double.
Nov 23 '08 #2
MrPickle
100 100+
I just tried it with a unsigned short & short, it doesn't work correctly for them either? No matter what the value it's meant to be reading in, it output 7543 :3
Nov 23 '08 #3
JosAH
11,448 Expert 8TB
Does a good old C union help? Something like this:

Expand|Select|Wrap|Line Numbers
  1. union enian {
  2.    unsigned char b[sizeof(double)];
  3.    unsigned short s;
  4.    unsigned int i;
  5.    unsigned long l;
  6.    float f;
  7.    double d;
  8. } buffer;
  9.  
Read n bytes in the buffer member, reverse n bytes and fetch one of the other members.

kind regards,

Jos
Nov 23 '08 #4
MrPickle
100 100+
I've never really used unions before.
Nov 24 '08 #5
JosAH
11,448 Expert 8TB
@MrPickle
Well, what's keeping you?

kind regards,

Jos
Nov 24 '08 #6
MrPickle
100 100+
@JosAH
I'm not to sure what they are exactly, a reduced class?
Nov 24 '08 #7
JosAH
11,448 Expert 8TB
@MrPickle
Yep, a very reduced class, even a reduced struct. All the members of a union start at the same place. So in the example above the buffer member takes the same memory as the double d or the int i. So, e.g., when I change the first four bytes of the buffer I directly change the bytes that make up the int i etc.

The buffer char member is just another 'view' of the int i or double d etc. which is exactly what you want although you may not realize that yet ;-)

kind regards,

Jos
Nov 24 '08 #8
MrPickle
100 100+
So what that was doing was moving everything along, 4 bytes in memory? How does that change the order of the variables in memory?
Nov 24 '08 #9
vmpstr
63
What JosAH was saying is that you can have

Expand|Select|Wrap|Line Numbers
  1. union myunion
  2. {
  3.     int i;
  4.     char bytes[4];
  5. } hello;
  6.  
then, you can do something like hello.i = 123;
That assigns the number 123 into the memory occupied by hello.i
However, because you have a union, this memory is also occupied by hello.bytes, which is a character array.

In turn, this means that you can manipulate the elements of hello.bytes array (like say, reverse their order), which will also change hello.i

You won't "change the order of the variables", but by reversing the bytes, you will... well, reverse the bytes.
Nov 24 '08 #10
MrPickle
100 100+
OH, I see. So whatever happens to bytes, also happens to i?

Can I read directly into bytes then? eg;
in.read(&hello.bytes[0], sizeof(int));

Ahh, yes. I get it, thanks for all the help.
Nov 24 '08 #11
vmpstr
63
@MrPickle
correct

@MrPickle
sure, why not

@MrPickle
all the credit goes to JosAH :D
Nov 24 '08 #12
MrPickle
100 100+
A couple questions, will this method work for std::string. I'm not sure it will, will I just have to read it in char by char until char == '\0'.

Have I done this right, because it's giving me linker errors when I try called Read<int>... or Read<unsigned short>...
Expand|Select|Wrap|Line Numbers
  1. template <typename T> union Endian {
  2.     unsigned char bytes[sizeof(T)];
  3.     T value;
  4. };
  5.  
  6. template<typename T> void Read(T& value, std::ifstream& in) {
  7.     Endian<T> e;
  8.     in.read((&e.bytes[0]), sizeof(T));
  9.  
  10.     for(int i = 0; i < sizeof(T); i++) {
  11.         bytes[i] = bytes[sizeof(T) - i]; //Not sure here, might cause access violation?
  12.     }
  13.  
  14.     value = e.value;
  15. }
Nov 24 '08 #13
Savage
1,764 Expert 1GB
Expand|Select|Wrap|Line Numbers
  1. bytes[i] = bytes[sizeof(T) - i]; //Not sure here, might cause access violation?
  2.  
  3. //It might.You mean:
  4.  
  5.  bytes[i] = bytes[sizeof(T) -1- i];
  6.  
That's the only error I see(it would compile with this error).
So which are the errors?
Can you post them?
Nov 25 '08 #14
JosAH
11,448 Expert 8TB
@Savage
Better change the loop boundary condition as well because as it is now you haven't done anything except for juggling those bytes back and forth ;-)

kind regards,

Jos
Nov 25 '08 #15
MrPickle
100 100+
I've fixed the linker bug now. There was an error in the header that it wasn't reporting.

The function I wrote doesn't work though, I don't really get what you was trying to say Jos
Nov 25 '08 #16
weaknessforcats
9,208 Expert Mod 8TB
It looks like your template is not in the same file as main().

Templates are not like functions. They are patterns the compiler copies and substitutes the type you specify on your code. That means the pattern has to be in the same file as the call.
Nov 25 '08 #17
MrPickle
100 100+
Ok, thanks. I've fixed it now.

I don't know why it's now working though.

It outputs this:

bytes[0] = }
bytes[1] =
bytes[2] =
bytes[3] =
value = 0

It should equal 123
Nov 25 '08 #18
JosAH
11,448 Expert 8TB
Change your loop to this:

Expand|Select|Wrap|Line Numbers
  1. for(int i= 0, j= sizeof(T); i < --j; i++) {
  2.    char   t= e.bytes[i]; 
  3.    e.bytes[i]= e.bytes[j];
  4.    e.bytes[j]= t;
  5. }
  6.  
kind regards,

Jos
Nov 25 '08 #19
MrPickle
100 100+
Yey, it's working. Thanks everybody.

Expand|Select|Wrap|Line Numbers
  1. template <typename T> union Buffer {
  2.     unsigned char bytes[sizeof(T)];
  3.     T value;
  4. };
  5.  
  6. template<typename T> void Read(T& value, std::ifstream& in) {
  7.     Buffer<T> e;
  8.     in.read(reinterpret_cast<char*>(&e.bytes[0]), sizeof(T));
  9.  
  10.     char t;
  11.     int j;
  12.     for(int i = 0; i < sizeof(T); i++) {
  13.         std::cout << i << " ";
  14.         j = (sizeof(T)-1)-i;
  15.         t = e.bytes[i];
  16.         e.bytes[i] = e.bytes[j];
  17.         e.bytes[j] = t;
  18.     }
  19.     std::cout << "\n";
  20.  
  21.     value = e.value;
  22. }
Nov 25 '08 #20
vmpstr
63
You want to be careful in your "swap the bytes" loop:
Suppose sizeof(T) is 4, then you have
1. swap byte 0 and byte 3
2. swap byte 1 and byte 2
3. swap byte 2 and byte 1
4. swap byte 3 and byte 0

In effect, step 3 cancels step 2 and step 4 cancels step 1 - so the bytes aren't swapped.

You might want to iterate only until sizeof(T)/2
Nov 25 '08 #21
MrPickle
100 100+
I'm not sure, but should I check if the machine is little endian? Otherwise it's going to make it big endian, right?
Nov 25 '08 #22
vmpstr
63
If it's little endian, it's going to make it big endian. If it's big endian, it's going to make it little endian.

This just converts it from one to another, it's up to you to figure out how you want to use it...
Nov 27 '08 #23
JosAH
11,448 Expert 8TB
The OP might want to look at the htons() and htonl() macros. They convert two and four byte integers to 'network byte' order, i.e. big endian order. Those macros don't do anything if the host machine happens to be a big endian machine.

kind regards,

Jos
Nov 27 '08 #24
MrPickle
100 100+
Alright, thanks for your help.
Nov 27 '08 #25

Sign in to post your reply or Sign up for a free account.

Similar topics

3
by: kelvSYC | last post by:
Are there any endianness concerns in C++, or does the compiler take care of those details? I ask because I'm not sure if code such as the following have consistent behavior on all platforms. ...
26
by: Case | last post by:
#include <string.h> int i; /* 4-byte == 4-char */ char data = { 0x78, 0x56, 0x34, 0x12 }; int main() { memcpy(&i, data, 4); /*
15
by: T Koster | last post by:
Hi group, I'm having some difficulty figuring out the most portable way to read 24 bits from a file. This is related to a Base-64 encoding. The file is opened in binary mode, and I'm using...
2
by: SSM | last post by:
Hi, Does C standard comment about "Endianness" to be used to store a structure/union variables? Thanks & Regards, Mehta
72
by: gamehack | last post by:
Hi all, I was thinking today, suppose we have the number n = 0xAB 0xFF which is equivalent to 44031 in decimal. In big endian it will be stored as 10101011 11111111 but in little endian...
18
by: friend.05 | last post by:
Code to check endianness of machine
6
by: Tomás | last post by:
Let's say you want to write fully portable code that will be writing files or sending data, and the data is text encoded using Unicode 16-Bit. Endianness comes into play. I'm writing code at the...
134
by: jacob navia | last post by:
Hi Suppose you have somewhere #define BOOL int and somewhere else typedef BOOL int;
18
by: Indian.croesus | last post by:
Hi, If I am right Endianness is CPU related. I do not know if the question is right in itself but if it is then how does C handle issues arising out of Endianness. I understand that if we pass...
5
by: Rahul | last post by:
Hi Everyone, I have a program unit which does >and << of an integer which is of 4 bytes length. The logic of shifting and action based on the result, assumes that the system is big-endian. ...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.