Hi,

I found a number of post talking about this in C, but could not solve it in C++.

I have 4 hex characters to represent a length. These need to be stored like this, in the case where length=16 (this online converter told me that 16 converts to A in hex).

char bufferlength[4] = {0x00,0x00,0x00,0x0A};

My problem. How do I get this, when all I have is length=300.


I have heard people mentioning DWORD, and also found the following code that converts an int n to hex. But I would like to find a built in function that handles the conversion for me.

for (int i=2*sizeof(int) - 1; i>=0; i--) {
            cout << "0123456789ABCDEF"[((n >> i*4) & 0xF)];
        }

Any ideas on how to convert 1 int into hex and store in the the char[4] array?

Many many thanks!

Recommended Answers

All 16 Replies

How exactly were you reading the converter that you linked? I think you may have read it incorrectly.

The digits in hexadecimal are 0-9 and A-F with A-F representing the decimal values 10-15 resp. There is no single digit that represents 16 in hex. If you convert decimal 16 to hex it's 0x10 (which numerically means one 16 plus zero 1s), decimal 32 to hex is 0x20 (two 16s plus zero 1s), and decimal 34 is 0x22 (two 16s plus two 1s), etc.

To produce output in hex, you need to set the hexadecimal flag on the output stream. In C++, this is accomplished through the use of stream manipulators and/or formatting flags.

if i understood you correct then this is the code:

int x = 300;
char out[4];
memcpy(out, &x, sizeof(int));

and then if you want to check if 'out' has the correct data you can do the following check:

printf("%d\n", MAKELONG(MAKEWORD(out[0], out[1]), MAKEWORD(out[2], out[3])));
int x = 300;
char out[4];
memcpy(out, &x, sizeof(int));

No offense but writing code means you are breaking the ANSI C++ standard.
This will execute very distinct in little ending to big ending machine.
so you better take this into account.

I'll try this right away.

I don't usually use hex. But I am writing data into a MIDI file, hence...

wow, I think you have a couple of concepts mixed-up here.

Hexadecimal numbers are just a notation for numbers in base 16 (like decimal is in base 10, binary in base 2, and octal in base 8). The computer stores only binary data, so any value is represented in binary. One special case is character representations (typically type "char" in C/C++). A char is still a binary number of 1 byte (0 to 255 value (unsigned), or 0x00 to 0xFF value (in hex)) which translates, through the ascii table, to a character that can be displayed.

The only reason why hex is used is because you can represent 1 byte with no more than 2 digits (16*16 = 256). So that is why a program like okteta and others are used to read binary data by showing there hex values (each pair of digits representing one byte) as opposed to a text editor (like notepad or emacs) that would translate the binary data with the ascii table into senseless characters. Because a binary file and its bytes were never meant to represent anything directly intelligible to a human being, but in the natural language of the computer instead (this is faster, smaller and more robust if there is no need for a human to inspect the file directly).

I'm saying all this because your question doesn't make much sense.

First of all, the decimal number 16 is 0x10 in hexadecimal notation not 0x0A (that is 10).

Second, the 0x thingy in front if the number is the C/C++ notation to indicate a literal constant written in hexadecimal notation, as this:

int i = 16; //is exactly the same as:
int i = 0x10;
//or, another example, with a bigger number:
int i = 525434; //is exactly the same as:
int i = 0x8047A;

So now the question is: Do you want to take a number stored in a variable and turn it into a printable string that is in hexadecimal notation? Or do you want to save the binary data to a file (such that okteta would display the correct hex-values)? That makes all the difference in the world.

First option: if you have a value (like an integer or any other binary data (remember that all data is binary in a computer)) and want to print its hex value to the console or terminal (cout). Then you would do this (taken directly from www.cplusplus.com):

int i = 16; //remember, this is 0x10 in hex notation
  cout.setf ( ios::hex, ios::basefield ); // set hex as the basefield
  cout.setf ( ios::showbase );            // activate showbase
  cout << i << endl;
  cout.setf ( 0, ios::showbase );         // deactivate showbase
  cout << i << endl;

Now, on the other hand, if you want to save any variable's value into a binary file. Then it would be like this:

char c = 'a'; // this is 1 byte, hex value = 0x61
  int i = 16;   // this is 4 bytes (32bit system), hex value = 0x10 (or 0x00000010)
  float f = 0.4; // well, that's more complicated a bit, so I won't bother.

  ofstream file("bin_output.dat",ios::out | ios::binary); //open a file for binary output.
  file.write((char*)&c,1); //write the one byte character, in binary.
  file.write((char*)&i,sizeof(int)); //write the integer in binary (actual size is system specific, other types can be used to fixed size)
  file.write((char*)&f,sizeof(float)); //write the float in binary.
  file.close();
  //now, if you open that file in okteta, you should see
  // 61 00 00 00 10 ... or 61 00 00 00 00 00 00 00 10 ...

>>But I am writing data into a MIDI file, hence...

Well, then it is option two in my last post. MIDI is a binary file. So hex are used extensively for inspecting the content manually and understanding its binary format because it is the representation that is the most convenient for that. But you have to understand that there is a BIG difference between the string value "10" and the hexadecimal value "10" (or 0x10 in C/C++ syntax). The best way to see is to look at the binary data (what is actually saved in the memory, i.e. 0s and 1s):

"10" is equal to hex: 0x313000, and binary: 0011 0001 0011 0000 0000 0000
0x10 is equal to binary: 0001 0000

thanks NicAx64, i did not think about the byte order..

dorien, if you just want to write an int to a file you can do that directly like this:

int x = 300;
FILE* file = fopen("1.db", "wb");
fwrite(&x, sizeof(int), 1, file);
fclose(file);

then you can read it back the same way..

Hi, Thanks for the extensive elaboration Mike.

I tried the first solution above, but memcpy gave me the error:

'mempcy' was not declared in this scope

Although my program has the following header files included (yes, I tried to delete the .h, but then it gave an error, so I kept it):

#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <ctime>

As for the writing to a midi file. I have most of it in place and it works fine like this:

ofstream myfile;
	myfile.open ("output.midi",ios::binary);

	//midi file header: defines file type/type-1 midi/1 track/tempo
	char bufferheader[18] = {0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x01,0x00,0x80,0x4D,0x54,0x72,0x6B};
	myfile.write(bufferheader,18);

	//number of characters to follow, incl bufferend -- need to calculate this dec2hex
	//restlength=number of notes x 10 - 1, now it is set fixed to 23
	char bufferlength[4] = {0x00,0x00,0x00,0x17};
	myfile.write(bufferlength,4);

	//music data, for each note: play note, and stop note
	//first note:
	char bufferdata[9]={0x00,0x90,0x3C,0x60,0x82,0x00,0xB0,0x3C,0x00};
	myfile.write(bufferdata,9);
	//from then on:
	char bufferdata2[10]={0x82,0x00,0x90,0x4C,0x60,0x82,0x00,0xB0,0x4C,0x00};
	myfile.write(bufferdata2,10);

	//eof
	char bufferend[4]={0x00,0xFF,0x2F,0x00};
	myfile.write(bufferend,4);

	myfile.close();

Since I got the rest of the midi file finally working, just need the length and later custom note value, I am looking for a solution to just calculate the bufferlength variable :-/

Do you think I can switch halfway the file to cout.setf?

you have spelled it wrong: mempcy should be memcpy..

Although my program has the following header files included (yes, I tried to delete the .h, but then it gave an error, so I kept it):

That's because you didn't use the proper name of the header.

These are not correct:

#include <stdio.h>  //pre-standard header, should not be used, except with legacy code
#include <stdio>    //no such header, probably what you errantly tried...

The proper standardized version of the header is:

#include <cstdio>

In general, the modern versions of the standard headers from C are the header name minus the ".h" with a "c" added at the beginning.

Pre-Standard, C headers:

#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
//many others

Post-Standard, C/C++ headers:

#include <cstdio>
#include <ctime>
#include <cmath>
#include <cstdlib>
//many others

@Fbody: super thanks. I did not know it needed the c in front of stdio.

Will try memcpy again. btw, I did spell it corretly, just made a mistake posting it.

Mmmm... I used cstdio in the header now (without .h) and there were no errors related to this.

Next I added the code:

int x = 300;
char out[4];
memcpy(out, &x, sizeof(int));

And got the following error:

../Music.h: In member function ‘void Music::exportmidi()’:
../Music.h:58:29: error: ‘memcpy’ was not declared in this scope
make: *** [project2.o] Error 1

do I need to include another header for memcpy to work? Or could it be something else?

Do some research on header files.

There are 3 different headers directly related to "strings", you'll need to add one of these:

  1. <string> is for the C++ string type.
  2. <string.h> is the pre-standard header for C-style string functions.
  3. <cstring> is the modern (Standard) implementation of <string.h>.

When you use the <c*> headers as opposed to the <*.h> headers, don't forget that everything is now in the std namespace:

int x = 300;
char out[4];
std::memcpy(out, &x, sizeof(int));

And memcpy is declared in <cstring>, not <cstdio>.

Sorry, found it, it is cstring.

Almost there:

I now use the code, which compiles excellent:

int x = 500;
char out[4];
memcpy(out, &x, sizeof(int));
myfile.write(out,4);

Instead of writing:

0x00,0x00,0x00,0x17

The file contains:

0x17,0x00,0x00,0x00

The midi file does work, so I am not sure if this is a big problem. As a solution, I wrote a little loop that moves the characters to the right. I hope that's ok to do?

int x = 23;
	char out[4]={0x00,0x00,0x00,0x00};
	memcpy(out, &x, sizeof(int));

	while (out[3]==0x00){
		out[3]=out[2];
		out[2]=out[1];
		out[1]=out[0];
		out[0]=0x00;
	}
	myfile.write(out,4);
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.