Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ Electronics ➜ Microprocessors ➜ Number bases

Number bases

Postings by administrators only.

Refresh page


Posted by Nick Gammon   Australia  (23,097 posts)  Bio   Forum Administrator
Date Tue 17 Feb 2015 02:42 AM (UTC)

Amended on Fri 20 Feb 2015 04:55 AM (UTC) by Nick Gammon

Message
This page can be quickly reached from the link: http://www.gammon.com.au/bases


We sometimes have queries on the Arduino forum about whether a variable contains a number "in hex". Or someone wants to store data "in binary" into a variable. This post attempts to address these issues.

Assigning a number to a variable



byte foo;

  foo = 42;       // assign 42, expressed in decimal, to foo
  foo = 052;      // assign 42, expressed in octal, to foo
  foo = 0b101010; // assign 42, expressed in binary, to foo
  foo = 0x2A;     // assign 42, expressed in hex, to foo


Each of the above assignment statements does exactly the same thing, at the machine code level.

In fact if you look at the assembler code the compiler generates, it doesn't even bother to reload the register containing 42, as it knows it is putting the same thing into foo every time:


  foo = 42;       // assign 42, expressed in decimal to foo
  a6:	8a e2       	ldi	r24, 0x2A	; 42
  a8:	80 93 00 01 	sts	0x0100, r24

  foo = 052;      // assign 42, expressed in octal to foo
  ac:	80 93 00 01 	sts	0x0100, r24

  foo = 0b101010; // assign 42, expressed in binary to foo
  b0:	80 93 00 01 	sts	0x0100, r24

  foo = 0x2A;     // assign 42, expressed in hex to foo
  b4:	80 93 00 01 	sts	0x0100, r24


So clearly the number in foo is not "in hex" or "in binary" it is just a number. The different ways of expressing it are for our convenience, nothing else.

For example, if someone asked you how old you were, you might reply "I am 42 years old". Now we would generally assume that to mean "decimal 42". However you might reply "in binary, I am 101010 years old", or "in hex, I am 2A years old". The different ways you express your age do not change the underlying number.

As an analogy, "forty-two" in English is "quarante-deux" in French, and "cuarenta y dos" in Spanish. Whatever the language, it's still 42.

Generally speaking, for humans, if no "base" is specified, we assume decimal (base 10), as does the C compiler.

To specify other bases in C (or C++) you use a prefix, like this:


  • No prefix: decimal
  • Prefix "0": octal (base 8), eg. 052
  • Prefix "0b": binary (base 2), eg. 0b101010 *
  • Prefix "0x": hex (base 16), eg. 0x2A


* Not every version of C might support the 0bxxx notation

Just to repeat that, a number is not stored inside a variable in hex, it is just a number. You can write hex in your code if you want to (as above) but the underlying number will be the same.

Converting bases programmatically


Sometimes you may have a hex string (eg. from a serial port, or an input file) that you need to convert into an integer for storing into a variable.

In that case you can use a function to do the conversion. One example is strtol (string to long). That takes character string as an input, a second argument (which can be NULL) which is set to point to where the conversion finishes, and a third argument, which is the base for the conversion.

For example, to convert from hex:


  const char myInput [] = "2A";
  foo = strtol (myInput, NULL, 16);


To convert from octal:


  const char myInput [] = "52";
  foo = strtol (myInput, NULL, 8);


To convert from binary:


  const char myInput [] = "101010";
  foo = strtol (myInput, NULL, 2);


In this case we don't use the prefix that the C compiler required for numeric literals, as we have told the function which base to use. We can also use it to convert a string into an integer (base 10) like this:


  const char myInput [] = "42";
  foo = strtol (myInput, NULL, 10);


Converting a variable for printing


A variable holding a number can be printed in any desired base, for example:


int foo = 42;
void setup ()
  {
  Serial.begin (115200);
  Serial.println (foo);      // print in decimal
  Serial.println (foo, HEX); // print in hex
  Serial.println (foo, OCT); // print in octal
  Serial.println (foo, BIN); // print in binary
  }  // end of setup

void loop () { }


Output:


42
2A
52
101010


It's the same variable, we are just "looking at it" in a different way. This example uses the Arduino HardwareSerial class which is derived from the Print class.

Converting a variable back to a string in different bases


If you don't want to print (maybe you want to write to a file) then there is another function that converts an integer back to a string: itoa


int foo = 42;
void setup ()
  {
  Serial.begin (115200);
  
  char buffer [10];
  
  itoa (foo, buffer, 10);   // convert to string, base 10
  Serial.println (buffer);

  itoa (foo, buffer, 16);   // convert to string, base 16
  Serial.println (buffer);

  itoa (foo, buffer, 8);    // convert to string, base 8
  Serial.println (buffer);

  itoa (foo, buffer, 2);    // convert to string, base 2
  Serial.println (buffer);  
  }  // end of setup

void loop () { }


Output:


42
2a
52
101010


Notice the subtle different that the "2a" in hex is lower-case compared to using Print earlier up.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


8,132 views.

Postings by administrators only.

Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.