Cast from int64 to byte array - c++

I wrote the following code which cast a long long to a byte array.
BYTE Buffer[8 +32];
BYTE * Temp = reinterpret_cast<BYTE*> (&Size);
Buffer[0] = Temp[0]; Buffer[1] = Temp[1]; Buffer[2] = Temp[2]; Buffer[3] = Temp[3];
Buffer[4] = Temp[4]; Buffer[5] = Temp[5]; Buffer[6] = Temp[6]; Buffer[7] = Temp[7];
//The next 32 bytes (Buffer[8] to Buffer[39]) contains the file name.
WriteFile(hFile,Buffer,40,&dwWrite,NULL);
Now the question is Is it safe to cast an int64 directly into bytes ? What are the possible bugs ?
I am well aware of other safer methods to do this (Bitshifting for example) but i want the code to be as fast as possible.
Thanks !

Problem is you write to disk with the byte ordering of the current machine. If you read it again on a machine with different byte ordering you will run into big trouble.
Thats why bit shifting would be the better way to do it.

Related

Char has incorrect number of bits

I'm currently working on a program that converts to and from base64 in Eclipse. However, I've just noticed that char values seem to have 7 bits instead of the usual 8. For example, the character 'o' is shown to be represented in binary as 1101111 instead of 01101111, which effectively prevents me from completing my project, as I need a total of 24 bits to work with for the conversion to work. Is there any way to either append a 0 to the beginning of the value (i tried bitshifting in both directions, but neither worked), or preventing the issue altogether?
The code for the (incomplete/nonfuntional) offending method is as follows, let me know if more is required:
std::string Encoder::encode( char* src, unsigned char* dest)
{
char ch0 = src[0];
char ch1 = src[1];
char ch2 = src[2];
char sixBit1 = ch0 >> 1;
dest[0] = ch2;
dest[1] = ch1;
dest[2] = ch0;
dest[3] = '-';
}
char for C/C++ language is always signed int8. So, it is excepted that you have only 7 useable bits - because one bit is used for sign storage.
Try to use unsigned char instead.
Either unsigned char or uint8_t from <stdint.h> should work. For maximum portability, uint_least8_t is guaranteed to exist.

Writing bytes in files the right way in C / C++ [Endianess]

I'm writing a program that creates MIDI files, and I'm trying to write the midi messages on a file.
I tested first all the way to create file from zero using the function fputc() and inputting byte per byte all the file, and it went well.
The problem came when I tried to write more than one byte at the same time (e.g. writing a short int or an int into the file), because the function fwrite() put the bytes backwards.
For example:
FILE* midiFile;
midiFile = fopen("test.mid", "wb");
short msg = 0x0006;
fwrite(msg, sizeof(msg), 1, midiFile);
fclose(midifile);
The output written int the file its 0x06 the 0x00, and not the expected: 0x00,0x06.
I read about that, and find that it's caused by the endianness; my Intel processor uses little endian so it writes variables bigger than 1 byte backwards (compared to a big endian machine).
I still need to correct that and write the bytes the way I want to develop my program.
My compiler doesn't identify functions like htonl() or similar (I don't know why) but I'm asking a way to do it, or how to write short's and int's on char arrays (especially short's).
Either write the bytes you want in order, one at a time...
or swap the bytes before you write them.
uint8_t msbyte = msg >> 8;
uint8_t lsbyte = msg & 0xFF;
uint8_t buffer[2];
// Big Endian
buffer[0] = msbyte;
buffer[1] = lsbyte;
/* Little endian
buffer[0] = lsbyte;
buffer[1] = msbyte;
*/
fwrite(&buffer[0], 1, sizeof(buffer), midiFile);
Swapping bytes:
uint16_t swap_bytes(const uint16_t value)
{
uint16_t result;
result = value >> 8;
result += (value & 0xFF) << 8;
return result;
}

Change first byte of s_addr

I would like to set the first byte of an s_addr variable, which is just an unsigned long.
Is this possible, and if so, how?
It is not an array of bytes, so I can't access it like this:
struct in_addr addr;
addr.s_addr[0] = 1; // Set this byte to the number 1, or in hex: 0x01
EDIT:
It turns out that I needed the last (i.e. the 4th) byte and not the first. But thanks to your help I now have:
*((char *)&addr.s_addr + 3) = 1;
One ugly and possibly unsafe (but nevertheless widely practised) way is like this:
*(char *)&addr.s_addr = 42;
If you know that addr.s_addr is an unsigned long though, and if by "first" byte you mean "least significant" byte, then you can use bitwise operators as a much safer alternative, e.g.
addr.s_addr &= ~0xffUL; // clear previous contents of LS byte
addr.s_addr |= 0x01UL; // set LS byte to 1
You take its address, interpret it as a pointer to a char and dereference it:
unsigned long ul;
*reinterpret_cast<char*>(&ul) = 0;
// ina is struct sockaddr_in
char* address = a1 = inet_ntoa(ina.sin_addr);
*address = x;
or
*(char*)&addr.s_addr = x;

Character array typecasting to integer

I have a char array and it holds value 0x4010, i want this value into an unsigned short varaible.
I did this by using atoi but getting short value as 0
unsigned short cvtValue = (unsigned short) atoi(aclDta);
character for 0x10 is DEL, i hope it is because of this.
Decimal is 6416
You don't need to convert the data with atoi, just cast it:
unsigned short cvtValue = *(unsigned short *)aclDta;
What you're asking doesn't make sense. 0x4010 in ascii is '#' followed by a 'data link escape'.
atoi, strtol etc are all about parsing ascii strings containing numbers - #\DLE isn't a number.
What you really seem to want is to treat the 0x4010 bytes as a single short.
here's a cheap way:
cvtValue |= ((short)aclData[0]) << 8;
cvtValue |= ((short)aclData[1]);
I'd comment, but apparently as a new user I can't? Anyway, antiduh's answer is more correct if you might ever port your application to platforms having different endienness.
char *str = "01";
unsigned short val = *(unsigned short *)str;
On little endien systems val == 0x3130. On big endien systems val == 0x3031.

unsigned char concatenation

I am creating a C++ program for communication with a gripper on a serial port.
I have to send a buffer of type "unsigned char [8]", but of these 8 bytes, 4 are entered from the keyboard, and 2 are the CRC, calculated at the time.
So, how can I concatenate several pieces in a single buffer of 8 bytes unsigned char?
For example:
unsigned char buffer[8];
----
unsigned char DLEN[1]={0x05};
----
unsigned char CMD[1]={0x01};
----
unsigned char data[4]={0x00,0x01,0x20,0x41};
----
unsigned char CRC[2]={0xFF,0x41};
----
how can I get this buffer: {0x05,0x01,0x00,0x01,0x20,0x41,0xFF,0x41} that is the union of DLEN,CMD,data and CRC?
This:
buffer[0] = DLEN[0];
buffer[1] = CMD[0];
buffer[2] = data[0];
buffer[3] = data[1];
buffer[4] = data[2];
buffer[5] = data[3];
buffer[6] = CRC[0];
buffer[7] = CRC[1];
An alternative solution is this:
Start off with an unsigned char array of 8 characters.
When you need to pass it off to other methods to have data inserted in them, pass it by reference like this: updateCRC(&buffer[6]) with the method signature taking an unsigned char pointer. Assuming you respect the respective sizes of the inputs, the result is the best of both worlds, handling the buffer as if they were separate strings, and not having to merge it into a single array afterwards.
You can use bit shifting, the << and >> operators, to get the appropriate fields to the right places in the buffer.
Something like buffer |= (DLEN << 7);
Just make sure your buffer is cleared to be all 0's first.
My version of hmjd's answer:
buffer[0] = DLEN[0];
buffer[1] = CMD[0];
std::copy(begin(data),end(data),buffer+sizeof DLEN+sizeof CMD);
std::copy(begin(CRC) ,end(CRC) ,buffer+sizeof DLEN+sizeof CMD+sizeof data);